2010-02-12 24 views
1

嗨,SQL Server 2005中分組問題之前的排名

這應該很容易,但我不太瞭解分組是如何工作的。

基本上我有2代表 「類別」 和 「項目」

分類
ID
類別名稱

物品
ID
類別ID ITEMNAME
照片
在sco

我想要做的是爲每個類別獲取1行,其中包含類別ID,類別名稱和屬於最高得分項目的照片。

所以我嘗試加入類別的項目和CategoryID分組。麻煩的是,我想要訂購商品,以便在分組進行分組之前將最高得分項目排在最前面,以確保該照片來自該分類中當前得分最高的商品。如果我選擇MAX(I.score),我可以獲得最高分,但我不知道如何獲得伴隨照片,因爲MAX(照片)顯然會按字母順序給我帶有最高文件名的照片。

我希望我解釋得很好。

回答

2

你可以嘗試像(完整的示例)

DECLARE @Categories TABLE(
    ID INT, 
    CategoryName VARCHAR(50) 
) 

DECLARE @Items TABLE(
    ID INT, 
    CategoryID INT, 
    ItemName VARCHAR(50), 
    Photo VARCHAR(50), 
    Score FLOAT 
) 

INSERT INTO @Categories (ID,CategoryName) SELECT 1, 'Cat1' 
INSERT INTO @Categories (ID,CategoryName) SELECT 2, 'Cat2' 

INSERT INTO @Items (ID,CategoryID,ItemName,Photo,Score) SELECT 1, 1, 'Item1', 'PItem1', 1 
INSERT INTO @Items (ID,CategoryID,ItemName,Photo,Score) SELECT 2, 1, 'Item2', 'PItem2', 2 
INSERT INTO @Items (ID,CategoryID,ItemName,Photo,Score) SELECT 3, 1, 'Item3', 'PItem3', 3 

INSERT INTO @Items (ID,CategoryID,ItemName,Photo,Score) SELECT 4, 2, 'Item4', 'PItem4', 5 
INSERT INTO @Items (ID,CategoryID,ItemName,Photo,Score) SELECT 5, 2, 'Item5', 'PItem5', 2 

SELECT * 
FROM (
      SELECT c.ID, 
        c.CategoryName, 
        i.Photo, 
        i.Score, 
        ROW_NUMBER() OVER(PARTITION BY i.CategoryID ORDER BY i.Score DESC) RowID 
      FROM @Categories c INNER JOIN 
        @Items i ON c.ID = i.CategoryID 
     ) CatItems 
WHERE RowID = 1 

使用ROW_NUMBER可以selet你需要的物品。

+0

不幸的是,這會產生一個錯誤 - 「OVER SQL結構或語句不被支持。」 – jonhobbs 2010-02-12 15:30:51

+0

無論如何設法讓它工作,它更像是一個「警告」,而不是一個錯誤。 – jonhobbs 2010-02-17 15:06:13

1

您需要首先彙總並回到這樣。 (如果更改分組,您需要更改JOIN)

SELECT 
... 
FROM 
    (
    select 
     max(Score) AS MaxScore, 
     CategoryID 
    FROM 
     Items 
    GROUP BY 
     CategoryID 
    ) M 
    JOIN 
    Items I ON M.CategoryID = I.CategoryID AND M.MaxScore = I.Score 
    JOIN 
    Categories C ON I.CategoryID = C.CategoryID 
+1

請記住,此解決方案將爲相同得分的項目生成多個結果。 – 2010-02-12 14:11:50

+0

與@Adam達成一致 - 我更喜歡ROW_NUMBER()解決方案,因爲您可以在OVER子句中進一步規定如何打破關係。 – 2010-02-12 14:15:15

+0

正確。但是,它確實比較好。我已經在所有的平衡方面測試了兩種方式(並且回答了兩種方式),數據集越大,我將使用聚合越多。說,「聯合頂部」可能是你想要的行爲 – gbn 2010-02-12 15:08:08

1

這是一個很常見的問題,而且SQL Server解決得不是很好。這樣的事情應該做的伎倆,雖然:

select 
    c.ID, 
    c.CategoryName, 
    item.* 

from Categories c 

join (
    select 
     ID, 
     CategoryID, 
     ItemName, 
     Photo, 
     Score, 
     (row_number() over order by CategoryID, Score desc) - 
      (rank() over order by CategoryID) as rownum 

     from Items) item on item.CategoryID = c.CategoryID and item.rownum = 0 

雖然沒有明確group by條款,這個(出於實用目的)組Categories記錄,並給你一個join版語句,它允許您查看的任何財產得分最高的項目。

+0

Right,row_number()從1開始雖然:) – Andomar 2010-02-12 14:21:32

+0

@Andomar:是的,但特定等級中的第一行與rank()函數具有相同的值,因此減去它們會使第一行爲0 。 – 2010-02-12 14:24:35

0

您可以使用行進行了排名每類項目:

select * 
from (
    select 
     row_number() over (partition by c.id order by i.score desc) rn 
    , * 
    from Categories c 
    join Items i on c.ID = i.CategoryID 
) sub 
where rn = 1 

在SQL 2005,你不能直接在where引用row_number(),所以它包裹在一個子查詢。

0

完全按照您的意見: 「類別ID,類別名稱和屬於最高得分項目的照片」。 - 現在我在這裏推測你真的意思是「......該類別中得分最高的項目」,不是嗎?)

Select CategoryID, c.Categoryname, Photo 
    From items i Join Categoiries c 
     On c.ID = i.CategoryId 
    Where Score = (Select Max(Score) From Items 
       Where CategoryID = i.CategoryId) 

如果你真的意味着對整個項目表中得分最高的項目,那麼就省略了謂語的子查詢

Select CategoryID, c.Categoryname, Photo 
    From items i Join Categoiries c 
     On c.ID = i.CategoryId 
    Where Score = (Select Max(Score) From Items) 

這兩個查詢將返回每組多行,如果有更多的比定義的組中的一個項目得分最高。