SQL - 查找快照日期之间新开始者和离开者的数量

SQL - Find number of new starters and leavers between snapshot dates

我有一个 SQL table staff 在特定日期拍摄快照并添加一行每个 staffID 和相应的 DateID

我需要了解自下一次 DateID 以来有多少员工加入,以及有多少员工离开。

所以在下面的示例 staff table 中,StaffID002003 来自 DateID A 没有 'left',DateID BstaffID004005006DateID 中不存在 'new'。

StaffID  DateID
007      C
005      C
006      B
005      B
004      B
001      B
003      A
002      A
001      A

我推测这些结果将如何出现在下面。

DateID  New  Leavers
A       0    2
B       3    2
C       1    3

我目前解决这个问题的唯一方法是遍历每个 DateID 之前的 DateID 并离开加入旧日期计算旧日期为空的行数新员工,并将 table 轮换为离职人员。

SELECT t1.DateID, count(*) AS Total

(SELECT *
FROM staff
WHERE DateID = 'B') t1

LEFT JOIN

(SELECT *
FROM staff
WHERE DateID = 'A') t2

ON t1.StaffID = t2.StaffID
WHERE t2.StaffID is null
GROUP BY t1.DateID

这种方法对于更大的 table 来说效率低得可怕,希望任何人都能想到一种在一个脚本中执行的方法。或者,一个仅适用于新员工的脚本和一个仅适用于离职人员的脚本也一样好。


应@Larnu 的要求,我添加了一个 snapshot table 来保存所有 DateID。 staff table 被过滤以仅显示每周的 DateID。

DateID Weekly Monthly Yearly
A      Y      Y       N
B      Y      N       N
C      Y      N       N
D      N      N       N
E      Y      Y       N
F      N      N       Y

LEADLAG window 函数在这里会有所帮助。

由于DateID不是连续的,你需要计算LEAD/LAG,然后加入

SELECT
  s.DateID,
  [New]   = COUNT(CASE WHEN s.PrevID IS NULL OR s.PrevID <> d.PrevDateID THEN 1 END),
  Leavers = COUNT(CASE WHEN s.NextID IS NULL OR s.NextID <> d.NextDateID THEN 1 END)
FROM (
    SELECT *,
      PrevDateID =  LAG(DateID) OVER (ORDER BY DateID),
      NextDateID = LEAD(DateID) OVER (ORDER BY DateID)
    FROM Dates d
) d
JOIN (
    SELECT *,
      PrevID =  LAG(s.DateID) OVER (PARTITION BY StaffID ORDER BY DateID),
      NextID = LEAD(s.DateID) OVER (PARTITION BY StaffID ORDER BY DateID)
    FROM staff s
) s ON s.DateID = d.DateID
GROUP BY
  s.DateID;