2010-09-07 5 views
2

J'ai une requête:gauche mysql join ascendant

SELECT reply.id, 
      reply.message, 
      reply.userid, 
      reply.date, 
      medal.id, 
      medal.url, 
      medal.name, 
      user.id, 
      user.name AS username 
    FROM posts AS reply 
LEFT JOIN users AS user ON reply.userid = user.id 
LEFT JOIN medals AS medal ON medal.userid = user.id 
GROUP BY reply.id 
ORDER BY reply.id ASC 

tout est OK, sauf que je reçois la médaille ascendante ne descend pas qui signifie que saisir la première médaille que l'utilisateur a - Je dois obtenir le dernier.

+1

Comment vous/nous savons que la médaille est la plus récente? –

+0

la question est pourquoi il l'obtient dans un ordre croissant – Wiika

+0

Votre requête ordonne par les valeurs 'reply.id' dans l'ordre croissant - nous ne savons rien de vos données ou structure de table, mais votre déclaration finale comprend" saisir la première médaille l'utilisateur a - j'ai besoin d'avoir le dernier. " Dans le contexte, cela signifie que vous voulez la dernière médaille ... –

Répondre

0

Vous pourriez peut-être créer une sous-requête ou une table temporaire pour les médailles au lieu de vous joindre directement aux médailles. La table temporaire serait la table des médailles mais triée DESC. La sous-requête serait LEFT JOIN (sélectionnez id, url, nom de l'ordre des médailles par desc) mais je pense que ce serait très lent et pas la meilleure option.

0

La solution la plus simple est de le faire:

ORDER BY reply.id ASC, medal.id DESC 

ET Retirez votre déclaration GROUP BY.

Vous pouvez filtrer les articles/utilisateurs qui ont plusieurs médailles par la suite (passez les lignes contenant les médailles que vous ne voulez pas).

L'option suivante consiste à sélectionner MAX(medal.id) dans une sous-requête, puis de se joindre à cela. Cela devient salissant, mais c'est faisable. Voici l'idée générale (vous devrez probablement renommer quelques alias de table, car ils sont utilisés plus d'une fois):

SELECT *, 
     medal.url, 
     medal.name 
FROM 
(
    SELECT reply.id, 
      reply.message, 
      reply.userid, 
      reply.date, 
      MAX(medal.id) AS medal_id, 
      user.id, 
      user.name AS username 
    FROM posts AS reply 
LEFT JOIN users AS user ON reply.userid = user.id 
LEFT JOIN medals AS medal ON medal.userid = user.id 
GROUP BY reply.id 
ORDER BY reply.id ASC 
) 
AS t 
LEFT JOIN medals AS medal ON medal.id = t.medal_id 
+0

la sous requête serait un bon choix pour moi en ce moment, je rejoins plus de 3 tables, j'ai essayé, (SELECT ID des médailles WHERE userid = user. id ORDER BY id DESC LIMI 1) Comme m_id ET ensuite rejoindre ON medal.id = m_id ut c'est trop lent – Wiika

+0

Ouais, vous ne voulez pas faire cela, ce serait l'exécution de requêtes 'N + 1'. En allant sur cette route, vous exécutez simplement deux requêtes, une sur une table temporaire ... ce n'est pas parfait mais je pense que c'est la meilleure option. – wuputah

1

Le fait que vous voyez le premier enregistrement par groupe est accidentelle. La sélection d'une colonne non agrégée et non spécifique à un groupe dans une requête GROUP BY entraîne la sélection d'un enregistrement non défini.

Pour une explication plus détaillée, lire: http://dev.mysql.com/tech-resources/articles/debunking-group-by-myths.html.

Une façon correcte de faire ce que vous faites est d'utiliser une sous-requête, dans laquelle vous sélectionnez la date de médaille maximale par groupe désiré.

Cette approche est décrite ici: http://dev.mysql.com/doc/refman/5.6/en/example-maximum-column-group-row.html