SQL - 查找快照日期之间新开始者和离开者的数量
SQL - Find number of new starters and leavers between snapshot dates
我有一个 SQL table staff
在特定日期拍摄快照并添加一行每个 staffID
和相应的 DateID
。
我需要了解自下一次 DateID
以来有多少员工加入,以及有多少员工离开。
所以在下面的示例 staff
table 中,StaffID
的 002
和 003
来自 DateID
A
没有 'left',DateID
B
有 staffID
的 004
,005
,006
在 DateID
中不存在 '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
LEAD
和 LAG
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;
我有一个 SQL table staff
在特定日期拍摄快照并添加一行每个 staffID
和相应的 DateID
。
我需要了解自下一次 DateID
以来有多少员工加入,以及有多少员工离开。
所以在下面的示例 staff
table 中,StaffID
的 002
和 003
来自 DateID
A
没有 'left',DateID
B
有 staffID
的 004
,005
,006
在 DateID
中不存在 '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
LEAD
和 LAG
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;