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

Posted

技术标签:

【中文标题】SQL - 查找快照日期之间的新开始者和离开者的数量【英文标题】:SQL - Find number of new starters and leavers between snapshot dates 【发布时间】:2021-11-24 18:41:47 【问题描述】:

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

我需要找出自下一次DateID 以来有多少员工加入,还有多少人离开了。

所以在下面的示例中 staff 在 DateID B 的表格中,StaffID002003 来自 DateID A 不存在所以有“左”和DateID @ 987654332@ 有 staffID004,005,006,它们在 DateID 中没有,所以是“新的”。

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,然后加入旧日期,计算旧日期为空的行以获取新员工的数量,然后交换为离校者圆桌。

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

这种方法对于一个更大的表来说效率非常低,希望任何人都可以在一个脚本中找到一种方法。或者,只为新员工准备的脚本和只为离职人员准备的脚本也一样好。


按照@Larnu 的要求,我添加了一个包含所有DateID 的snapshot 表。 staff 表被过滤为仅显示每周的 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

【问题讨论】:

'A' 是什么“日期”? 'A' 是在 'C' 之前还是之后?你怎么知道?当你“约会”'Z' 时会发生什么,你有约会 'AA' 吗? 是的,'A' 将是第一个日期,然后是 B,然后是 C。这是虚拟数据,因此您可以在 Z 结束或继续 AA。这个真的没有结束日期。 我建议使用有意义的数据,@WillacyMe。使用字母来定义日期是非常令人困惑的。这些日期的顺序是ORDER BY LEN(DateId), DateID,这直观... 日期(字母?)也是连续的吗?例如,您是否可以缺少“日期”'D' 但有一个“日期”'e' 实际数据使用 4 位数字,每个快照的大小都会增加。我在这里使用了字母,以便更清楚地区分 datesID 和 StaffID。将其更改为 AAAA、AAAB、AAAC 或 0001、0002 等是否更有意义? 【参考方案1】:

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

由于DateIDs 不是连续的,你还需要计算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;

【讨论】:

非常感谢。我不知道 LEAD 和 LAG 窗口函数。

以上是关于SQL - 查找快照日期之间的新开始者和离开者的数量的主要内容,如果未能解决你的问题,请参考以下文章

查找交易列表的新日期

获取开始日期和结束日期之间的日期

需要在 SQL Server 2008 中查找两个日期之间的日期

查找两个日期之间的差异 Oracle SQL

SQL 查询 - 在日期和时间之间查找

MySQL - 如何查找日期在开始日期到结束日期之间的记录