【问题标题】:SQL Query for SCD Type 2SCD 类型 2 的 SQL 查询
【发布时间】:2021-06-18 17:04:59
【问题描述】:

我收到下表,存在以下问题:

从数据集中创建一个渐变维度类型 2。 EMPLOYEE 表有每个员工的每日记录。 类型 2 - 将具有有效数据和到期日期。

Employee ID Date Name Manager ID
123 1-Mar John Smith 1
123 2-Mar John Smith 1
123 3-Mar John Smith 2
123 4-Mar John Smith 3
123 5-Mar John Smith 3

我相信我的目标表应该是这样的:

Employee ID Name Manager ID Effective Date Expiration Date
123 John Smith 1 1-Mar 3-Mar
123 John Smith 2 3-Mar 4-Mar
123 John Smith 3 4-Mar Null

我尝试了以下查询:

SELECT employee_id, name, manager_id,
CASE
    WHEN LAG(manager_id) OVER() != manager_id THEN e.date 
    WHEN e.date = FIRST_VALUE(e.date) OVER() THEN e.date
    ELSE NULL
END as "Effective Date",
CASE 
    WHEN LEAD(manager_id) OVER() != manager_id THEN LEAD(e.date) OVER()
    ELSE NULL
END as "Expiration Date"
FROM employee e

我的结果表如下:

Employee ID Name Manager ID Effective Date Expiration Date
123 John Smith 1 1-Mar Null
123 John Smith 1 Null 3-Mar
123 John Smith 2 3-Mar 4-Mar
123 John Smith 3 4-Mar Null
123 John Smith 3 Null Null

有没有人知道我可以通过什么方式改变我的查询以实现我的目标表,基于我迄今为止所取得的成就?我不知何故只需要产生 3 个经理 ID,但 distinct 不起作用。另外,我需要找到一种方法来组合每个经理 ID 的生效日期和到期日期。任何帮助都将不胜感激。

【问题讨论】:

  • 抱歉,我会尽快尝试找出解决方法并纠正我的问题。谢谢你告诉我。
  • 如果您将示例添加为 DDL+DML,那么人们会更容易回答。
  • 您能否澄清一下,经理是否可以回到以前的经理,即同一经理可以在不同的时间点重复吗?
  • 你并没有像那样存储你的日期,是吗?
  • 看起来您需要的是 GROUP BY 查询,MIN()MAX()on Date 列作为 EffectiveExpiryLEAD()LAG() 是解决问题的错误方法

标签: sql sql-server tsql scd scd2


【解决方案1】:

以下内容满足您的要求,并展示了如何添加 DDL+DML。它可能有点令人费解,但我看不出有明显的简化方法。

此解决方案考虑了经理重复的可能性。而且它并不假设每一天都会存在,所以如果一天不见了,它仍然可以工作。

declare @Test table (EmployeeID int, [Date] date, [Name] varchar(32), ManagerID int);

insert into @Test (EmployeeID, [Date], [Name], ManagerID)
values
(123, '1 Mar 2021', 'John Smith', 1),
(123, '2 Mar 2021', 'John Smith', 1),
(123, '3 Mar 2021', 'John Smith', 2),
(123, '4 Mar 2021', 'John Smith', 3),
(123, '5 Mar 2021', 'John Smith', 3);
--(123, '6 Mar 2021', 'John Smith', 2);

select EmployeeId, [Name], ManagerId, MinDate
  -- Use lead to get the last date of the next grouping - since it could in theory be more than one day on
  , lead(MinDate) over (partition by EmployeeId, [Name] order by Grouped) MaxDate
from (
  -- Get the min and max dates for a given grouping
  select EmployeeId, [Name], ManagerId, min([Date]) MinDate, max([Date]) MaxDate, Grouped
  from (
    select *
       -- Sum the change in manager to ensure that if a manager is repeated they form a different group
       , sum(Lagged) over (order by Date asc) Grouped
    from (
      select *
        -- Lag the manager to detect when it changes
        , case when lag(ManagerId,1,-1) over (order by [Date] asc) <> ManagerId then 1 else 0 end Lagged
      from @Test
    ) X
  ) Y
  group by EmployeeId, [Name], ManagerId, Grouped
) Z
order by EmployeeId, [Name], Grouped;

返回:

EmployeeId Name ManagerId MinDate MaxDate
123 John Smith 1 2021-03-01 2021-03-03
123 John Smith 2 2021-03-03 2021-03-04
123 John Smith 3 2021-03-04 NULL

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 2020-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多