2014-01-29 47 views
0

我有這個表:選擇頂部1,最大2場

+------+-------+------------------------------------+ 
| id | rev | class        | 
+------+-------+------------------------------------+ 
| 1 | 10 | 2         | 
| 1 | 10 | 5         | 

| 2 | 40 | 6         | 
| 2 | 50 | 6         | 
| 2 | 52 | 1         | 

| 3 | 33 | 3         | 
| 3 | 63 | 5         | 
+------+-------+------------------------------------+ 

我只需要在那裏轉,然後類列具有最大值的行。

+------+-------+------------------------------------+ 
| id | rev | class        | 
+------+-------+------------------------------------+ 
| 1 | 10 | 5         | 
| 2 | 52 | 1         | 
| 3 | 63 | 5         | 
+------+-------+------------------------------------+ 

查詢成本對我很重要。

+0

你能否讓這個更具可讀性?並添加一個問題或者你有什麼問題?你還有什麼嘗試...... – Mzf

+0

嘗試在這裏創建一個sql小提琴:http://sqlfiddle.com/ –

+2

你使用什麼數據庫?爲什麼人們設計表格,使得名爲'id'的列具有重複值? –

回答

0

我想你的意思是:最大rev和最大class。如果沒有,請澄清如果沒有兩個字段具有最高值的行,應該怎麼做。

select id 
,  max(rev) 
,  max(class) 
from table 
group 
by  id 

如果你指的revclass使用這個總價值:

select id 
,  max 
,  rev 
from table 
where id in 
     ( select id 
      ,  max(rev + class) 
      from table 
      group 
      by  id 
     ) 
1

只是滿足,它同時具有最大值條件的行?

這是SQL Fiddle;

SELECT h.id, h.rev, h.class 
FROM ( SELECT id, 
       MAX(rev) rev, 
       MAX(class) class 
     FROM Herp 
     GROUP BY id) derp 
INNER JOIN Herp h 
    ON h.rev = derp.rev 
    AND h.class = derp.class; 
+0

「內連接」添加了什麼?沒有它,我認爲它已經很好。 –

+0

如果沒有特定'id'具有MAX值的記錄,則不應該有記錄;考慮添加一行,如(3,64,4)。 – Avarkx

1

最快的方式可能是對t(id, rev)t(id, class)索引,然後做:

select t.* 
from table t 
where not exists (select 1 
        from table t2 
        where t2.id = t.id and t2.rev > t.rev 
       ) and 
     not exists (select 1 
        from table t2 
        where t2.id = t.id and t2.class > t.class 
       ); 

SQL Server是在優化方面相當聰明,所以聚合方法可能是一樣好。但是,就性能而言,這只是一堆索引查找。

+0

[我可以內聯鏈接嗎?](http://sqlfiddle.com/#!2/829b4/1)如果是這樣,我認爲你是正確的 - 它必須在特定情況下確定哪些表單在整體上表現更好,考慮到實際的表格使用情況(讀取/插入/等等)。 – Avarkx

+0

我的表總計行數超過5000萬條記錄。 –

1

這是一個SQL 2012示例。非常簡單的表格和PARTITION功能。

基本上,將每個ID作爲分區/組,按降序對其他字段的值進行排序,爲每個字段分配一個遞增的RowId,然後只取第一個。

select id, rev, [class] 
from 
    (
     SELECT id, rev, [class], 
     ROW_NUMBER() OVER(PARTITION BY id ORDER BY rev DESC, [class] desc) AS RowId 
     FROM sample 
    ) t 
where RowId = 1 

這裏是SQL Fiddle

請記住,這一點也適用標準中的示例數據集,而不是在問題的標題說兩個領域的MAX。

+0

謝謝,但我已經測試過這個解決方案,而且速度很慢。我有一個有5000萬行的巨大表,我需要少於30秒的查詢執行時間。 –

+0

然後在正確的順序上添加三個字段的覆蓋索引 - id,rev desc和class desc。 – Charles

+0

聯接解決方案顯着快於窗口功能。 –