我正在尝试使用DENSE_RANK()OVER PARTITION为某些数据创建一组排名。数据按日期,日期时间和状态排序。它是我需要排序的日期时间和状态,下面是所需的排名输出。
我使用了各种DENSE_RANK和ROW_NUMBER组合,但未能获得正确的分组。 是否有可能获得我需要的排名?
答案 0 :(得分:1)
使用lag()
和case
表达式将ctstatus
与之前的ctstatus
进行比较,并在不同时返回1
。这假设您要重置每个人和每天的排名,如果不是将其从partition by
移动到order by
子句的over()
的开头。然后使用sum() over()
将运行总计作为rnk
。
;with cte as (
select t.*
/* compare ctstatus with previous ctstatus, when different return by 1 */
, inc = case when ctstatus = lag(ctstatus) over (
partition by
description -- for each person
, atdate --for each day ?
order by atdatetime
) then 0 else 1 end
from t
)
select
atdatetime
, atdate
, atext
, description
, ctstatus
, rnk = sum(inc) over (partition by description, atdate order by atdatetime)
from cte;
答案 1 :(得分:0)
根据您的描述和示例数据,我们无法知道要分组或分区的内容,所以我现在忽略了这一点。也就是说,您可以使用SUM() OVER
窗口聚合来实现此目的。
示例数据
if object_id('tempdb..#x') is not null drop table #x;
create table #x
(
ATDATETIME datetime,
ATDATE date,
ATEXT varchar(10),
CTSTATUS varchar(30)
);
create clustered index cl_x on #x(ATDATETIME); -- for a sort-free execution plan
insert #x values
(getdate()-1.90, cast(getdate()-1.90 as date), 1397, 'BK tomorrow...'),
(getdate()-1.85, cast(getdate()-1.85 as date), 1397, 'AVAILABLE'),
(getdate()-1.83, cast(getdate()-1.83 as date), 1397, 'AVAILABLE'),
(getdate()-1.81, cast(getdate()-1.81 as date), 1397, 'AVAILABLE'),
(getdate()-1.75, cast(getdate()-1.75 as date), 1397, 'AVAILABLE'),
(getdate()-1.71, cast(getdate()-1.71 as date), 1397, 'Went away'),
(getdate()-1.67, cast(getdate()-1.67 as date), 1397, 'AVAILABLE'),
(getdate()-1.63, cast(getdate()-1.63 as date), 1397, 'AVAILABLE'),
(getdate()-1.60, cast(getdate()-1.60 as date), 1397, 'AVAILABLE'),
(getdate()-1.56, cast(getdate()-1.56 as date), 1397, 'AVAILABLE'),
(getdate()-1.55, cast(getdate()-1.55 as date), 1397, 'Snuck out for beer'),
(getdate()-1.50, cast(getdate()-1.50 as date), 1397, 'AVAILABLE'),
(getdate()-1.46, cast(getdate()-1.46 as date), 1397, 'AVAILABLE');
<强>解决方案强>
select ATDATETIME, ATDATE, ATEXT, CTSTATUS, RNK =
SUM(IIF(CTSTATUS = 'AVAILABLE' AND CTSTATUS_LAG1 = 'AVAILABLE',0,1))
OVER (ORDER BY ATDATETIME)
from
(
select *, CTSTATUS_LAG1 = LAG(CTSTATUS, 1) OVER (ORDER BY ATDATETIME)
from #x
) tlag;
结果
ATDATETIME ATDATE ATEXT CTSTATUS RNK
----------------------- ---------- ---------- ------------------------------ -----------
2017-10-30 14:00:11.990 2017-10-30 1397 BK tomorrow... 1
2017-10-30 15:12:11.990 2017-10-30 1397 AVAILABLE 2
2017-10-30 15:40:59.990 2017-10-30 1397 AVAILABLE 2
2017-10-30 16:09:47.990 2017-10-30 1397 AVAILABLE 2
2017-10-30 17:36:11.990 2017-10-30 1397 AVAILABLE 2
2017-10-30 18:33:47.990 2017-10-30 1397 Went away 3
2017-10-30 19:31:23.990 2017-10-30 1397 AVAILABLE 4
2017-10-30 20:28:59.990 2017-10-30 1397 AVAILABLE 4
2017-10-30 21:12:11.990 2017-10-30 1397 AVAILABLE 4
2017-10-30 22:09:47.990 2017-10-30 1397 AVAILABLE 4
2017-10-30 22:24:11.990 2017-10-30 1397 Snuck out for beer 5
2017-10-30 23:36:11.990 2017-10-30 1397 AVAILABLE 6
2017-10-31 00:33:47.990 2017-10-31 1397 AVAILABLE 6