[英]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.