按另一列分组的一列的最低值排序

时间:2013-01-29 19:21:36

标签: sql-server tsql group-by sql-order-by ranking

这在标题中很难解释,但这里有一张表:

CATEGORY_ID   COUNT   GROUPING
1             130     H
2              54     B
3             128     C
4              70     D
5              31     E
6              25     F
7              64     A
8              59     F
9              66     B
10             62     E
11            129     C
12             52     G
13             27     A
14            102     A
15            101     C

我正在尝试编写一个查询来获取TOP 5 CATEGORY_ID,首先按整体COUNT排序,但然后根据该组使用另一个CATEGORY_ID不管他们是COUNT,都在那个群体中。所以,如果我想基于这个规则(我可能解释得很差)的上述TOP 5,我的结果将是:

CATEGORY_ID   COUNT   GROUPING
6             25      F <-- THE LOWEST COUNT OVERALL
8             59      F <-- THE NEXT LOWEST IN GROUP 'F'
13            27      A <-- THE NEXT LOWEST OVERALL
7             64      A <-- THE NEXT LOWEST IN GROUP 'A'
14            102     A <-- THE NEXT LOWEST IN GROUP 'A'

我在这里和其他地方看了很多(尝试过像RANK(),DENSE_RANK(),GROUPING SETS等等 - 大多数情况下都是黑暗中的刺伤)并且四处都是围墙。

编辑:另外一件事是我需要随机打破COUNT的关系。因此,例如,如果COUNT对于所有行都是0,则返回的第一个组应该是随机的。我在下面的两个答案中都将NEWID()添加到ORDER BY,但没有运气,我试过这个。

谢谢。

2 个答案:

答案 0 :(得分:5)

; with groups as (
  select
    grouping,
    min(count) as group_min
  from categories
  group by grouping
)
select top 5 c.category_id, c.count, c.grouping
from categories c
join groups g on c.grouping = g.grouping
order by g.group_min, c.count

Sql Fiddle

编辑:

要在关联时进行随机化,您可以使用row_number()newid()为每个组添加随机订单:

; with groups as (
  select
    grouping,
    row_number() over (order by newid()) as random,
    min(count) as group_min
  from categories
  group by grouping
)
select top 5
  c.category_id, c.count, c.grouping
from categories c
join groups g on c.grouping = g.grouping
order by g.group_min, g.random, c.count

Sql Fiddle

答案 1 :(得分:2)

更新:使用RANK()代替ROW_NUMBER(),因此任何关联记录(例如所有计数为0时)都具有相同的排名。这允许NEWID()按顺序为您提供随机结果。

;WITH CatByCount AS (
    SELECT 
        CATEGORY_ID, 
        COUNT,
        GROUPING,
        RANK() OVER (ORDER BY COUNT) AS ORD
    FROM theTaBle
)
SELECT TOP 5 CATEGORY_ID, COUNT, GROUPING 
FROM (
    SELECT I.CATEGORY_ID, O.ORD, I.COUNT, I.GROUPING
    FROM CatByCount O
    CROSS APPLY (
        SELECT A.CATEGORY_ID, A.COUNT, A.GROUPING
        FROM theTable A
        WHERE A.GROUPING = O.GROUPING
    ) I
) X
ORDER BY X.ORD, X.COUNT, NEWID()

更新了Sql Fiddle