2013-11-10 61 views
0

我試圖獲得給定GROUP BY條件的TOP X結果。 我目前使用的是這樣的:如何爲每個GROUP BY條件返回多個行

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結果?

例如,從TOP X以下數據

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

假設X是2,我想獲得的行:

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

頂部x結果是什麼表? –

+0

新增了一個例子,比較清楚? – Noam

+1

如果'id = 2'有'15 13 13'結果怎麼辦?那麼你會顯示3嗎? – zerkms

回答

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

+0

任何方式來避免子查詢?將需要檢查,但假設這將是一個性能殺手。這是爲了在數十億行的桌子上運行。 – Noam

+0

@Noam:爲什麼不把操作數據存儲在一個單獨的表(碎片,分區,不管)? – zerkms

+1

@Noam你可以在你的問題中提到它。谷歌上有很多關於這個話題的例子:[TOP X在Mysql#1](http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax- row-per-group-in-sql /)或[TOP X在Mysql#2中](http://stackoverflow.com/questions/12113699/get-top-n-records-for-each-group-of-grouped - 結果) –