2010-02-27 4 views
4

J'ai posé une question similaire before seulement pour découvrir plus tard que ce que je pensais être la réponse ne marchait pas parce que je n'avais pas posé la bonne question (et n'avais pas remarqué que le répondeur m'a dit ça). Pour revisiter, j'ai un tableau de comparaisons. J'essaye de sélectionner la rangée avec la version maximum pour chaque ensemble de deux étudiants. Donc ce que je faisais:Sélection de Max de deux colonnes (revisité)

SELECT subID1, subID2, stu1,stu2,comparisonID,MAX(stu1vers+stu2vers) AS maxvers 
FROM comparisons 
WHERE assignmentID=9 AND stu1!=stu2 
GROUP BY stu1,stu2; 
+--------+--------+------+------+--------------+---------+ 
| subID1 | subID2 | stu1 | stu2 | comparisonID | maxvers | 
+--------+--------+------+------+--------------+---------+ 
|  15 |  11 | 1 | 6 |   64 |  6 | 
|  11 |  3 | 6 | 1 |   55 |  5 | 
+--------+--------+------+------+--------------+---------+ 

ne fonctionnerait pas, car là je ne avais besoin la ligne où maxvers était 6. La réponse que je suis arrivé la dernière fois était:

SELECT subID1,subID2,stu1,stu2, comparisonID 
FROM comparisons WHERE stu1Vers + stu2Vers = (
    SELECT MAX(stu1Vers+stu2Vers) 
    FROM comparisons 
    WHERE stu1 != stu2 AND assignmentid=9 
) AND stu1!=stu2 AND assignmentid=9 
GROUP BY stu1,stu2; 

Ce que je pensais vraiment que travaillé - seulement pour découvrir que cela demande la version maximale dans la table pour cette assignation, puis cherche les lignes qui correspondent à cette version maximale. Mais ce n'est pas bon, parce que deux étudiants pourraient avoir un numéro de version inférieure:

+--------+--------+------+------+--------------+---------+ 
| subID1 | subID2 | stu1 | stu2 | comparisonID | maxvers | 
+--------+--------+------+------+--------------+---------+ 
|  44 |  23 | 37 | 36 |   153 |  2 | 
|  44 |  36 | 37 | 39 |   156 |  3 | 
|  44 |  34 | 37 | 40 |   154 |  3 | 
|  36 |  23 | 39 | 36 |   95 |  3 | 
|  36 |  34 | 39 | 40 |   96 |  4 | 
... 
+--------+--------+------+------+--------------+---------+ 

Là, je dois sélectionner tous les enregistrements, comme chaque combinaison de Stu1 et stu2 est unique. Comment puis-je les lignes où max (sub1vers + sub2vers) pour chaque combinaison de stu1, stu2 (c'est-à-dire, comme dans la première table là-haut, où j'ai toujours juste besoin de comparaison d'ID 64).

Répondre

2

Modifier La requête spécifique à MySQL produirait des valeurs incorrectes pour les colonnes non agrégées. Veuillez utiliser la requête portable à la place.

En supposant que vous êtes sous MySQL (basé sur l'étiquette de votre question ainsi que votre requête SQL originale), alors vous êtes en mesure de publier la déclaration suivante:

SELECT subID1, subID2,stu1,stu2,comparisonID,MAX(stu1vers+stu2vers) AS maxvers 
FROM comparisons 
WHERE assignmentID=9 AND stu1!=stu2 
GROUP BY LEAST(stu1,stu2), GREATEST(stu1,stu2); 

Si vous avez besoin d'une meilleure portabilité (en étant capable d'émettre la requête sur par exemple Postgres), vous avez besoin d'une requête légèrement plus complexe, ici en utilisant un seul JOIN:

SELECT c1.subID1, c1.subID2,c1.stu1,c1.stu2,c1.comparisonID,c2.versmax 
FROM comparisons AS c1 
INNER JOIN (
    SELECT 
    LEAST(stu1,stu2) AS stuA, 
    GREATEST(stu1,stu2) AS stuB, 
    MAX(stu1vers+stu2vers) AS versmax 
    FROM comparisons 
    WHERE assignmentID=9 AND stu1<>stu2 
    GROUP BY stuA, stuB 
) AS c2 
ON ((c1.stu1=c2.stuA AND c1.stu2=c2.stuB) OR 
    (c1.stu2=c2.stuA AND c1.stu1=c2.stuB) 
    ) AND c1.stu1vers+c1.stu2vers=c2.versmax 
WHERE c1.assignmentID=9 AND c1.stu1<>c1.stu2; 

Notez que la requête plus portable peut encore revenir deux lignes pour une paire unique d'étudiants si les deux combinaisons donnent le même maxvers (sauf si vous décidez de prévu une règle de discrimination entre les deux), par exemple:

+--------+--------+------+------+--------------+---------+ 
| subID1 | subID2 | stu1 | stu2 | comparisonID | maxvers | 
+--------+--------+------+------+--------------+---------+ 
|  15 |  11 | 1 | 6 |   64 |  6 | 
|  11 |  3 | 6 | 1 |   55 |  6 | 
+--------+--------+------+------+--------------+---------+ 
+0

Ces deux requêtes me donnent réellement des résultats différents. Le top me donne le bon max (stu1vers + stu2vers), mais avec le mauvais ID de comparaison. Le bas semble avoir raison. –

+0

Oui, cette première suggestion ne fonctionnera pas. Si vous n'incluez pas de champ dans la commande, la valeur obtenue peut être pour n'importe quelle ligne, pas nécessairement la valeur de la ligne maximale. –

+0

Vous voulez dire dans le 'groupe par'. :) – vladr

1

SELECT subID1, subID2, stu1,stu2,comparisonID,MAX(stu1vers+stu2vers) AS maxvers
FROM comparisons
WHERE assignmentID=9 AND stu1!=stu2
GROUP BY stu1,stu2

ORDER BY MAX(stu1vers+stu2vers) DESC
LIMIT 1

Ou suis-je pense mal?

+0

Malheureusement, j'ai besoin de sélectionner plusieurs lignes, donc cela ne fonctionnera pas –

+0

Si vous supprimez la LIMITE? – Phoexo

+0

Cela ne fonctionnera pas pour deux raisons. 1) il n'ignore pas l'ordre de stu1 et stu2. 2) Il a le même problème que la première suggestion de Vlad: il renvoie dans certains cas les mauvais identifiants de comparaison. –

1

Désolé de ne pas avoir bien compris votre question la dernière fois que vous avez demandé. Que diriez-vous ceci:

SELECT 
    subID1, 
    subID2, 
    T3.stu1, 
    T3.stu2, 
    comparisonID, 
    stu1vers + stu2vers AS maxvers 
FROM (
    SELECT assignmentId, stu1, stu2, MAX(vers) AS maxvers 
    FROM (
     SELECT 
      assignmentId, 
      stu1vers + stu2vers AS vers, 
      LEAST(stu1, stu2) AS stu1, 
      GREATEST(stu1, stu2) AS stu2 
     FROM comparisons 
     WHERE stu1 <> stu2) AS T1 
    GROUP BY assignmentId, stu1, stu2 
) AS T2 
JOIN comparisons AS T3 
    ON T2.stu1 = LEAST(T3.stu1, T3.stu2) 
    AND T2.stu2 = GREATEST(T3.stu1, T3.stu2) 
    AND T2.maxvers = T3.stu1vers + T3.stu2vers 
    AND T2.assignmentId = T3.assignmentId 
WHERE T3.assignmentId = 9 

Ce groupe de Stu1 et stu2 pour trouver les versions maximales, l'auto-joint à la table de comparaison pour récupérer les colonnes restantes pour la ligne correspondante. L'ordre de stu1 et stu2 est supposé non pertinent.

Questions connexes