2017-09-27 56 views
0

我需要針對MS SQL 2012數據庫編寫查詢,以識別存在7個或更多連續日期的記錄。我無法寫入數據庫,下面是我的輸出示例;查詢順序日期> = 7 - MSSQL2012

enter image description here

突出顯示的條目是什麼,我想輸出的例子。下面是我用來解決這個問題的查詢;

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運行哪些截斷是不連續的數據,預先感謝您!

回答

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; 
+0

完美,謝謝! –

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 
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; 

enter image description here