我需要针对MS SQL 2012数据库编写一个查询,该数据库标识存在7个或更多连续日期的记录。我无法写入数据库,下面是我的输出示例;
突出显示的条目是我想要输出的示例。以下是我用来做到这一点的查询;
Declare @From DATETIME
SET @From = '2017-09-11 00:00:00.000'
;WITH RAW AS (SELECT
ps.ReportDate ReportDate,
min (ps.StartTime) Start,
max (ps.EndTime) Finish,
e.LastName
FROM PayrollSegment ps, Employee e
WHERE ps.EmployeeKey = e.EmployeeKey AND ps.ReportDate > @From
GROUP BY e.LastName, ps.ReportDate )
SELECT * FROM RAW ORDER BY LastName
我不能为我的生活找出我必须对抗CTE来截断不是连续的数据,谢谢你提前!!
答案 0 :(得分:1)
这似乎是一个典型的“岛屿”问题。使用两个CTE,第一个用于查找岛(创建数据组),第二个用于选择您感兴趣的组(即具有7行或更多行的组)。
这样的事情应该可以解决问题......
WITH GroupedData AS
(
SELECT ps.ReportDate,
ps.StartTime,
ps.EndTime,
e.EmployeeKey,
e.LastName,
row_number() OVER(PARTITION BY e.LastName ORDER BY ps.StartTime)-datediff(DAY,@From, ps.StartTime) AS GroupId
FROM PayrollSegment AS ps
INNER JOIN Employee e ON ps.EmployeeKey = e.EmployeeKey
WHERE ps.ReportDate > @From
)
, Group7Day AS
(
SELECT g.EmployeeKey,
g.GroupId
FROM GroupedData g
GROUP BY g.EmployeeKey,
g.GroupId
HAVING count(1) >= 7
)
SELECT gd.ReportDate,
gd.StartTime,
gd.EndTime,
gd.LastName
FROM GroupedData gd
INNER JOIN Group7Day g7 ON g7.EmployeeKey = gd.EmployeeKey AND g7.GroupId = gd.GroupId;
答案 1 :(得分:0)
您可以尝试查找每位员工的连续期间。以下是示例安装脚本:
declare @From datetime = '20170911'
declare @PayrollSegment table(ReportDate datetime, StartTime datetime, EndTime datetime, EmployeeKey varchar(10))
insert into @PayrollSegment(ReportDate, StartTime, EndTime, EmployeeKey) values
('20170912', '20170912', '20170912', 'Acton'),
('20170913', '20170913', '20170913', 'Acton'),
('20170914', '20170914', '20170914', 'Acton'),
('20170915', '20170915', '20170915', 'Acton'),
('20170918', '20170918', '20170918', 'Acton'),
('20170919', '20170919', '20170919', 'Acton'),
('20170920', '20170920', '20170920', 'Acton'),
('20170921', '20170921', '20170921', 'Acton'),
('20170922', '20170922', '20170922', 'Acton'),
('20170923', '20170923', '20170923', 'Acton'),
('20170924', '20170924', '20170924', 'Acton'),
('20170925', '20170925', '20170925', 'Acton'),
('20170926', '20170926', '20170926', 'Acton'),
('20170912', '20170912', '20170912', 'Ahn'),
('20170913', '20170913', '20170913', 'Ahn'),
('20170914', '20170914', '20170914', 'Ahn'),
('20170915', '20170915', '20170915', 'Ahn')
首先查找所有期间开始(即没有ReportDate的记录 - 此员工为1):
select
ReportDate as PeriodStart
from @PayrollSegment ps
where ps.ReportDate >= @From and not exists(select 1 from @PayrollSegment ps2 where ps.EmployeeKey = ps2.EmployeeKey and ps2.ReportDate = DATEADD(day, -1, ps.ReportDate))
然后在此查询中添加相应的期末(即当前员工之后的最小ReportDate,对于同一员工,没有ReportDate + 1的记录):
select
ReportDate as PeriodStart
, (select min(ps3.ReportDate) from @PayrollSegment ps3 where ps3.ReportDate > ps.ReportDate and not exists(select 1 from @PayrollSegment ps4 where ps4.EmployeeKey = ps3.EmployeeKey and ps4.ReportDate = DATEADD(day, 1, ps3.ReportDate))) as PeriodEnd
from @PayrollSegment ps
where ps.ReportDate >= @From and not exists(select 1 from @PayrollSegment ps2 where ps.EmployeeKey = ps2.EmployeeKey and ps2.ReportDate = DATEADD(day, -1, ps.ReportDate))
这会为您提供连续日期的列表。只需选择至少7天的句号:
; with cte as (
select
ReportDate as PeriodStart
, (select min(ps3.ReportDate) from @PayrollSegment ps3 where ps3.ReportDate > ps.ReportDate and not exists(select 1 from @PayrollSegment ps4 where ps4.EmployeeKey = ps3.EmployeeKey and ps4.ReportDate = DATEADD(day, 1, ps3.ReportDate))) as PeriodEnd
from @PayrollSegment ps
where ps.ReportDate >= @From and not exists(select 1 from @PayrollSegment ps2 where ps.EmployeeKey = ps2.EmployeeKey and ps2.ReportDate = DATEADD(day, -1, ps.ReportDate))
)
select * from cte where DATEDIFF(day, PeriodStart, PeriodEnd) >= 7
答案 2 :(得分:0)
declare @PayrollSegment table(ReportDate datetime, StartTime datetime, EndTime datetime, EmployeeKey varchar(10))
insert into @PayrollSegment(ReportDate, StartTime, EndTime, EmployeeKey) values
('20170925', '20170925', '20170925', 'Botten'),
('20170926', '20170926', '20170926', 'Botten'),
('20170914', '20170914', '20170914', 'Boyle'),
('20170915', '20170915', '20170915', 'Boyle'),
('20170916', '20170915', '20170915', 'Boyle'),
('20170918', '20170918', '20170918', 'Boyle'),
('20170919', '20170919', '20170919', 'Boyle'),
('20170920', '20170920', '20170920', 'Boyle'),
('20170921', '20170921', '20170921', 'Boyle'),
('20170922', '20170922', '20170922', 'Boyle'),
('20170923', '20170923', '20170923', 'Boyle'),
('20170924', '20170924', '20170924', 'Boyle'),
('20170925', '20170925', '20170925', 'Boyle'),
('20170926', '20170926', '20170926', 'Boyle'),
('20170927', '20170926', '20170926', 'Boyle'),
('20170912', '20170912', '20170912', 'Bridge'),
('20170913', '20170913', '20170913', 'Bridge'),
('20170915', '20170915', '20170915', 'Bridge'),
('20170916', '20170915', '20170915', 'Bridge'),
('20170919', '20170919', '20170919', 'Bridge'),
('20170920', '20170920', '20170920', 'Bridge');
with c as
(
select ReportDate, EmployeeKey, dateadd(day, -1 * dense_rank() over(partition by EmployeeKey order by ReportDate), ReportDate) as grp
from @PayrollSegment
),
c1 as
(
select EmployeeKey, min(ReportDate) as start_range, max(ReportDate) as end_range
from c
group by EmployeeKey, grp
having datediff(day, min(ReportDate), max(ReportDate) ) >= 7
)
select *
from @PayrollSegment p join c1
on p.EmployeeKey = c1.EmployeeKey and p.ReportDate between c1.start_range and c1.end_range;