如果最近的记录具有特定值,则尝试在缓慢变化的维度表中计算用户的连续值

问题描述 投票:0回答:1

我有一个表,其中包含用户、条目日期、标志和条目类型。看起来像这样。

User InDate   Flag  Type
1   2023-06-01  E   A
2   2023-06-01  E   AS
3   2023-06-01  E   A
4   2023-06-01  I   NULL
1   2023-03-01  E   A
2   2023-03-01  E   AS
3   2023-03-01  E   A
4   2023-03-01  I   AS
1   2022-12-01  I   NULL
2   2022-12-01  E   AS
3   2022-12-01  E   A
4   2022-12-01  E   AS

我正在尝试查找截至当前日期具有连续“AS”类型的用户数量。在此示例中,假设我在 2023 年 6 月 30 日运行。我的想法是使用滞后函数根据日期获取用户之前的条目值,将其与当前值进行比较,然后为其分配 1 并对每个用户求和。这是我尝试过的代码:

WITH Lagged AS (
    SELECT [User],
           Indate,
           [Type],
           Flag,
           LAG([Type]) OVER (PARTITION BY [User] ORDER BY Indate) AS prev_val
    FROM #MYtest
    WHERE InDate >= '20220601'
    and InDate < getdate())

SELECT [User], COUNT(*)  as consecutive_count
FROM (
    SELECT [User],
           CASE WHEN [Type] = prev_val and [Type] like '%AS%' THEN 1 ELSE 0 END AS consecutive_indicator
    FROM Lagged
) AS T
WHERE consecutive_indicator = 1
GROUP BY [User];

但是我得到了结果:

User consecutive_count
2   2
4   1

我想要得到什么(预期结果):

User consecutive_count
2    3

因为用户 2 是唯一具有最新类型“AS”的用户。我是否应该在最终计数中添加 1,然后将滞后表连接回原始表以检查最新状态是否为“AS”?有更好的方法吗?

非常感谢任何提示或建议。 用于重新创建我在 SQL Server 中测试的数据的代码:

CREATE TABLE #MYTest([User] int, InDate date,Flag varchar(1),Type  varchar(2))
INSERT INTO #MYTest
values(1,'2023-06-01','E','A'),    
(2,'2023-06-01','E','AS'),    
(3,'2023-06-01','E','A'),    
(4,'2023-06-01','I',NULL),    
(1,'2023-03-01','E','A'),    
(2,'2023-03-01','E','AS'),    
(3,'2023-03-01','E','A'),    
(4,'2023-03-01','I','AS'),
(1,'2022-12-01','I',NULL),    
(2,'2022-12-01','E','AS'),    
(3,'2022-12-01','E','A'),    
(4,'2022-12-01','E','AS')

我还尝试连接回原始表,仅查找当前状态为“AS”的表,并将所有计数加 1 以说明当前状态,但遇到了这样的极端情况:

User,InDate,Flag,Type
5,2023-06-01,E,AS
5,2023-03-01,E,A
5,2022-12-01,E,AS
5,2022-09-01,E,AS

结果是: 用户,连续计数 5, 2 这是因为 12/1/2022 的 AS 类型与 09/01/2022 标志相同,结果为 1,然后我添加了 1。Doh!

sql sql-server window-functions
1个回答
0
投票

抱歉偏离了您的方法,我认为您唯一缺少的部分是以某种方式将结果限制为每个用户的最新行。

我发现构建一些增量计数器和 max() 函数作为更多窗口函数更容易,并且根本不使用滞后。

我认为以下内容对您有用:

with counters as
(
  select *,
  row_number() over(partition by usr order by indate) as rn,
  row_number() over(partition by usr, typ order by indate) as consec
  from mytest
 ),
 recency as 
 (
 select *,
 max(rn) over(partition by usr) as max_rn
 from counters
   )
 select usr, consec 
 from recency 
 where max_rn = rn
 and typ = 'AS'

SQL 小提琴

© www.soinside.com 2019 - 2024. All rights reserved.