开发者

Selecting Max of two columns (revisited)

I asked a similar question before only to later discover that what I thought was the answer didn't work because I hadn't asked the right question (and hadn't noticed that the answerer told me this). To revisit, I have a table of comparisons. I'm trying to select the row with the maximum version for each set of two students. So what I had been doing:

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 |
+--------+--------+------+------+--------------+---------+

wouldn't work, because there I only needed the row where maxvers was 6. The answer I got last time was:

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;

Which I really thought worked - only to discover that this queries for the maximum version in the table for that assignment, then looks for rows that match that maximum version. But this is no good, because two students might have a lower version number:

+--------+--------+------+------+--------------+---------+
| 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 |
...
+--------+--------+------+------+--------------+---------+

There I need to select all of those records, as each combination of stu1 and stu2 is unique. How do I the rows where max(sub1vers+sub2vers) for each combination of stu1,stu2 (that is, as in the first table up there, where I still need just comparisonID 64).


Edit The MySQL-specific query would yield incorrect values for the non-aggregate columns. Please use the portable query instead.

Assuming that you are running under MySQL (based on your question's tag as well as your original SQL query), then you are able to issue the following statement:

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);

If you require better portability (also being able to issue the query on e.g. Postgres), you need a slightly more complex query, here using a single 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;

Note that the more portable query may still return two rows for a unique pair of students if both combinations yield the same maxvers (unless you decide to provided a rule to discriminate between the two), e.g.:

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


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

Or am I thinking wrong?


Sorry that I didn't understand your question properly last time you asked. How about this:

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

This groups by stu1 and stu2 to find the maximum versions, the self-joins with the comparison table to fetch the remaining columns for the corresponding row. The order of stu1 and stu2 is assumed to be irrelevant.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜