基于顺序和值的SQL分组

时间:2015-09-18 15:18:23

标签: sql tsql

我有一张桌子

loctype    order
ACUTE      1
ACUTE      2
COM        3
COM        4
ACUTE      5
COM        6

我想要一个按顺序对组进行排名的查询,所以我想要的结果是:

loctype    order    group_order
ACUTE      1        1
ACUTE      2        1
COM        3        2
COM        4        2
ACUTE      5        3
COM        6        4

有没有办法在不使用游标的情况下将其作为SQL查询执行?

2 个答案:

答案 0 :(得分:1)

实现此目标的一种方法是row_number()识别组的差异,然后dense_rank()与最小值的差异。代码如下:

select t.*, dense_rank(minid) over (order by minid) as group_order
from (select t.*, min(id) over (partition by loctype, grp) as minid
      from (select t.*
                   (row_number() over (order by [order]) -
                    row_number() over (partition by loctype order by [order])
                   ) as grp
            from t
           ) t
     ) t;

另一种方法(对于SQL Server 2012+)是使用lag()累积和:

select t.*,
       sum(case when loctype = prev_loctype then 0 else 1 end) over
           (order by id) as group_order
from (select t.*, lag(loctype) over (order by id) as prev_loctype
      from t
     ) t

答案 1 :(得分:0)

我尝试了SQL Server 2008的给定解决方案(这就是我必须使用的)。不幸的是,它并没有给出相应的正确结果,但是根据Gordon的例子,我想出了这个,它确实提供了所需的结果。

SELECT 
    *
FROM
    (       
        SELECT
            *,
            DENSE_RANK() over(order by (SELECT ISNULL(MAX(#tmp.[order]),0) FROM #tmp WHERE #tmp.[order]<t.[order] AND #tmp.loctype <> t.loctype)) as intorder
        FROM
            #tmp AS t
    ) AS u

这给出了

loctype order group_order
ACUTE   1     1
ACUTE   2     1
COM     3     2
COM     4     2
ACUTE   5     3
COM     6     4

基本上它隐藏了DENSE_RANK()内部的初始排序。如果没有DENSE_RANK(),它看起来像这样:

选择     * 从     (
        选择             *              (SELECT ISNULL(MAX(#tmp。[order]),0)FROM #tmp WHERE #tmp。[order] t.loctype)as intgroup         从             #tmp AS t     )AS u

并给出了这个结果:

loctype order   intgroup
ACUTE   1       0
ACUTE   2       0
COM     3       2
COM     4       2
ACUTE   5       4
COM     6       5

然后,临时组的顺序可以是DENSE_RANKed,以提供所需的结果。