如何为每个GROUP BY条件返回多行

时间:2013-11-10 08:14:23

标签: mysql sql group-by query-optimization greatest-n-per-group

我正在尝试获得给定GROUP BY条件的TOP X结果。 我现在正在使用这样的东西:

SELECT * FROM 
        (SELECT id  
            FROM myTable 
            WHERE id IN (x1, x2, ..., xn) GROUP BY id ORDER BY grade DESC 
        ) t1 
        INNER JOIN myTable t2 ON t2.id=t1.id

id是一个非唯一的INT索引字段,每个值有多行。

这会返回每个id,即最佳成绩的行。如何将其转换为返回每个id的TOP X结果?

例如,对于以下数据

id  grade
2   10
2   13
2   15
3   20
4   16
4   55
4   45
4   35
4   25
5   1

假设TOP X中的X是2,我想获得行:

id grade  
2  15  
2  13  
3  20  
4  50  
4  40  
5  1  

2 个答案:

答案 0 :(得分:0)

也许,这样的事情?

SELECT m.*
FROM (
  SELECT id
  FROM myTable 
  WHERE id IN (1, 3)
  GROUP BY id
) AS ids
RIGHT JOIN myTable AS m ON ids.id = m.id
WHERE
  m.id = ids.id AND
  m.grade IN (
    SELECT TOP 5 t.grade
    FROM myTable AS t
    WHERE t.id = ids.id
    ORDER BY t.grade DESC
  );

UPD: 或者,甚至

SELECT m.*
FROM myTable AS m
WHERE
  m.id IN (1, 2) AND
  m.grade IN (
    SELECT TOP 5 t.grade
    FROM myTable AS t
    WHERE t.id = m.id
    ORDER BY t.grade DESC
  );

答案 1 :(得分:0)

这取决于你是否想要退回关系。

如果您想要返回关系,可以使用以下方法:

CREATE TABLE grades (
  id INT,
  grade INT
);

INSERT INTO grades VALUES (1, 2);
INSERT INTO grades VALUES (1, 3);
INSERT INTO grades VALUES (1, 4);
INSERT INTO grades VALUES (1, 5);

INSERT INTO grades VALUES (2, 5);
INSERT INTO grades VALUES (2, 5);
INSERT INTO grades VALUES (2, 5);
INSERT INTO grades VALUES (2, 4);

INSERT INTO grades VALUES (3, 3);
INSERT INTO grades VALUES (3, 4);

INSERT INTO grades VALUES (4, 3);

SELECT id, grade
  FROM grades g
WHERE (
   SELECT COUNT(DISTINCT grade) FROM grades
   WHERE id = g.id
      AND grade >= g.grade
) <= 2;

输出:

ID     GRADE
1   4
1   5
2   5
2   5
2   5
2   4
3   3
3   4
4   3

如果您不想要领带,请使用DISTINCT:

SELECT DISTINCT id, grade
  FROM grades g
WHERE (
   SELECT COUNT(DISTINCT grade) FROM grades
   WHERE id = g.id
      AND grade >= g.grade
) <= 2;

输出:

ID     GRADE
1   4
1   5
2   5
2   4
3   3
3   4
4   3

SQLFiddle: SQLFiddle