简体   繁体   English

基于顺序和值的SQL分组

[英]SQL grouping based on order and value

I have a table 我有桌子

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

I want a query that will apply rankings to groups in order, so my desired outcome is: 我想要一个查询,该查询将按顺序将排名应用于组,所以我想要的结果是:

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

Is there a way to do this as a SQL query without resorting to cursors? 有没有一种方法可以作为SQL查询而不使用游标来做到这一点?

One method for achieving this is a difference of row_number() to identify the groups and then dense_rank() on the minimum value. 实现此目的的一种方法是,区别row_number()来标识组,然后dense_rank()最小值上的dense_rank() The code looks like: 代码如下:

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;

Another method (for SQL Server 2012+) is to use lag() with a cumulative sum: 另一种方法(对于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

I tried the given solution for SQL Server 2008 (that's what I have to work with). 我尝试了给定的SQL Server 2008解决方案(这是我必须使用的解决方案)。 Unfortunately it didn't give quite the correct results, however working from Gordon's example, I came up with this, which does give exactly the desired result. 不幸的是,它并没有给出正确的结果,但是根据戈登的示例,我想到了这一点,但确实给出了理想的结果。

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

This gives 这给

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

Essentially it hides an initial ordering inside the DENSE_RANK(). 本质上,它在DENSE_RANK()中隐藏了初始顺序。 Without the DENSE_RANK() it looks like this: 没有DENSE_RANK(),它看起来像这样:

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

And gives this result: 并给出以下结果:

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

The interim group order can then be DENSE_RANKed to give the desired outcome. 然后可以将临时组顺序进行DENSE_RANKed以给出所需的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM