历史数据更新

History data update

我们需要检查 Auto Parking Membership activity。当个人成为会员时,详细信息最初将与 MemberID、MemberShipDate、ActivityDate、ActivityMonthEnd、IsActive、ActiveYTD 一起存储。此数据将存储到 DW table。这是我们存储到 DW 的 daily 数据。 最后一个字段“ActiveYTD”没有什么复杂的逻辑。默认值为‘Y’,该字段值取决于‘IsActive’字段。当 IsActive = ‘N’时,从 IsActive 字段值从 Y 变为 N 之日起,‘ActiveYTD’字段值也更新为‘N’。
但是有一个业务规则,这个 IsActive 字段可以是 Active 和 Inactive 任​​意次数。不知道为什么会有这样的规定

注意:- 如果假设 IsActive 字段值在 2022 年 2 月 15 日为“N”并且在 2022 年 4 月 20 日之前处于非活动状态。当然 ActivityYTD 字段也会从 Y 变为N 基于以上公式逻辑。但由于 IsActive 字段在 2022 年 4 月 21 日更改为“Y”。ActivityYTD 也将更改为“Y”。但业务定义是当 IsActive 字段从 N 更改为 Y 时。ActiveYTD 字段在前面的行中永远不应为“N”。从 2022 年 2 月 15 日至今的所有行都应为“Y”。因此,如果从 2022 年 2 月 15 日到年底的 IsActive 值 =“N”,则从 2022 年 2 月 15 日开始的 ActiveYTD 也将为“N”。 ActivityDate 和 ActivityMonthEndDate 都是来自维度 table 的键。 (例如:- 20220215、20220228) 基于上面定义的业务逻辑,我创建了一个查询

Select mainData.MemberID, mainData.MembershipDate, mainData.ActivityDateKey, mainData.ActivityMonthEndDateKey,  InactiveData.InactiveDate, mainData.IsActive, 
Case When mainData.IsAcitve =’N’ and (mainData.ActivityDateKey/100 >= InactiveData.InactiveDate/100) and (mainData.ActivityDateKey/10000 = InactiveData.InactiveDate/10000) then ‘Y’ else ‘N’ end as AcitveYTD
From History_AutoParkingMemberShip mainData
Left Outer Join
(
     Select MemberID, Max(ActivityDateKey) as InactiveDate
     From AutoParkinigMembership
     Where IsActive = ‘N’ 
     Group by MemberID
) InactiveData on InactiveData.MemberID = MainData.MemberID

但是这个查询并不是 100% 产生正确的结果。因为我还需要查找 IsActive 值 = ‘Y’ 时是否有任何情况,然后我更新 ActiveYTD 值‘Y’ 的先前值需要更新为‘N’。

MemberID  MemberShipDate  ActivityDateKey  ActivityMonthEndDateKEy  InactiveDate, IsActive  ActiveYTD

1001      2019/06/17      20220101         20220131                 Null          Y     Y
1001      2019/06/17      20220102         20220131                 Null          Y     Y 
...       ....             ...               ...                    ...          ...    ...
1001      2019/06/17      20220201         20220228                 Null          Y     Y 
1001      2019/06/17      20220215         20220228                 20220420      N     N
...       ....             ...               ...                    ...          ...    ...
1001      2019/06/17      20220420         20220430                 20220420      N     N 
1001      2019/06/17      20220421         20220430                 Null          Y     Y
1001      2019/06/17      20220422         20220430                 Null          Y     Y

现在您看到上面的数据,其中 ActiveYTD 字段永远不应具有值 = 'N',因为该成员 1001 从 2022 年 4 月 21 日起再次活跃。这有点混乱。有人可以就如何改进查询提出您的想法吗?

您可以使用 Window 函数来做到这一点。

想法是找到按 ActivityDateKey 排序的那一年 'Y' 的最后一个 IsActive 值。

之前的任何行的 ActiveYTD 都应为 'Y'。 如果在最后一个 'Y' 之后有任何 IsActive='N' 的记录,请将其标记为 'N'.

下面的 Window 函数将给出 'Y' 的计数,直到当前行。

COUNT(CASE WHEN IsActive='Y' THEN 1 END) 
OVER( PARTITION BY MemberID,ActivityDateKey/10000
ORDER BY ActivityDateKey Desc ROWS UNBOUNDED PRECEDING )

最终查询:

SELECT 
tab.*
,CASE WHEN 
COUNT(CASE WHEN IsActive='Y' THEN 1 END) 
OVER( PARTITION BY MemberID,ActivityDateKey/10000
ORDER BY ActivityDateKey Desc ROWS UNBOUNDED PRECEDING ) >0 THEN 'Y' ELSE 'N' END ActiveYTD
FROM AutoParkinigMembership tab
ORDER BY ActivityDateKey  

db<>fiddle: Try here

注意:以上fiddle是sqlserver-2014的,但在2012应该也能用。

数据集:

MemberID MemberShipDate ActivityDateKey ActivityMonthEndDateKEy IsActive
1001 2019-06-17 20220102 20220131 Y
1001 2019-06-17 20220201 20220228 Y
1001 2019-06-17 20220215 20220228 Y
1001 2019-06-17 20220420 20220430 N
1001 2019-06-17 20220421 20220430 Y
1001 2019-06-17 20220422 20220430 N

输出:

MemberID MemberShipDate ActivityDateKey ActivityMonthEndDateKEy IsActive ActiveYTD
1001 2019-06-17 20220102 20220131 Y Y
1001 2019-06-17 20220201 20220228 Y Y
1001 2019-06-17 20220215 20220228 Y Y
1001 2019-06-17 20220420 20220430 N Y
1001 2019-06-17 20220421 20220430 Y Y
1001 2019-06-17 20220422 20220430 N N