在SQL Server 2005中分组问题之前的排名

时间:2010-02-12 13:56:52

标签: sql sql-server sql-server-2005 tsql

HI,

这应该很容易,但我对分组的工作原理还不够了解。

基本上我有两个表“类别”和“项目”

分类
ID
类别名称


ID
类别ID ITEMNAME
照片
分数

我想要做的就是为每个类别获取1行,其中包含类别ID,类别名称和属于最高得分项目的照片。

所以我尝试将类别加入项目并按CategoryID分组。麻烦的是,我想订购物品,以便在进行分组之前,最高得分项目位于顶部,以确保照片来自该类别中当前得分最高的项目。如果我选择MAX(I.score)我可以获得最高分,但我不知道如何获得附带照片,因为MAX(照片)显然会按字母顺序给我带有最高文件名的照片。

我希望我已经解释得那么好。

5 个答案:

答案 0 :(得分: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,您可以选择所需的项目。

答案 1 :(得分: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

答案 2 :(得分: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 ed语句,允许您查看最高级别的任何属性得分项目。

答案 3 :(得分: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中,您无法直接在row_number()中引用where,因此它包含在子查询中。

答案 4 :(得分: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)

如果定义的组中有多个项目与最高分数相关,则这两个查询都将返回每个组的多个行。