2016-11-28 108 views
0

卡住了一個項目。我在sql服務器中發現了這個代碼,它發現了一個職員的重複日期匹配,但是當我試圖擴展它以縮小它到時間範圍也彼此重疊時,我被卡住了。時間和日期衝突 - Sql Server

因此,有一個叫做「花名冊」同列「 STAFFID」,「日期」,「開始」,「終結」

SELECT 
y.[Date],y.StaffID,y.Start,y.[End] 
FROM Rosters y 
INNER JOIN (SELECT 
[Date],StaffID, COUNT(*) AS CountOf 
FROM Rosters 
GROUP BY [Date],StaffID 
HAVING COUNT(*)>1) 
dd ON y.[Date]=dd.[Date] and y.StaffID=dd.StaffID 

它返回所有重複日期爲每個工作人員的表,我想添加邏輯 -

y.Start <= dd.[End] && dd.Start <= y.[End] 

這是可能的方式我目前正在做呢?任何幫助,將不勝感激。

@TT。抱歉,下面可能是一個更好的視覺的解釋 -

例如,這將是名冊表

ID  Date  Start End 
1 01/01/2000 8:00 12:00 
1 01/01/2000 9:00 11:00 
2 01/01/2000 10:00 14:00 
2 01/01/2000 8:00 9:00 
3 01/01/2000 14:00 18:00 
3 02/02/2002 13:00 19:00 

而且我試圖返回下面究竟是什麼的例子,因爲他們是對ID,日期和時間範圍衝突的唯一2行(開始 - 結束)

ID  Date  Start End 
1 01/01/2000 8:00 12:00 
1 01/01/2000 9:00 11:00 
+0

dd子查詢可能包含多個開始和結束,您想要比較哪個值? –

+1

你應該用單詞而不是T-SQL解釋你想要的。不要專注於解決方案,而是解釋你想要做什麼。 –

+0

@NolanShang - 我試圖把它包括在子查詢中,但它不返回任何東西,我有一種感覺,我正在做一些小錯誤,但它是我畫空白的那些東西之一:( – Bev0

回答

1

試試這個

with cte as 
(
    SELECT ROW_NUMBER() over (order by StaffID,Date,Start,End) as rno 
    ,StaffID, Date, Start, End 
    FROM Rosters 
) 
select distinct t1.* 
from cte t1 
inner join cte t2 
on(t1.rno <> t2.rno 
    and t1.StaffID = t2.StaffID 
    and t1.Date = t2.Date 
    and t1.Start <= t2.End 
    and t1.End >= t2.Start 
    ) 
order by t1.rno 

製造@ iamdave的回答有些變化

+0

謝謝,這由於iamdave的解決方案中沒有提到的唯一ID,因此證明rno的加入是有用的。是否可以將結果分組在一行中? – Bev0

2

這是您需要將結果過濾爲重疊時間範圍的邏輯,儘管我認爲這可以在沒有找到重複的中間步驟的情況下處理。如果你只是用一些測試數據和所需輸出張貼您的源表的模式,你會得到一個更好的答案:

declare @t table (RowID int 
        ,ID int 
        ,DateValue date  --\ 
        ,StartTime Time  -- > Avoid using reserved words for your object names. 
        ,EndTime Time  --/ 
        ); 
insert into @t values 
(1,1, '01/01/2000', '8:00','12:00') 
,(2,1, '01/01/2000', '9:00','11:00') 
,(3,2, '01/01/2000', '10:00','14:00') 
,(4,2, '01/01/2000', '8:00','9:00' ) 
,(5,3, '01/01/2000', '14:00','18:00') 
,(6,3, '02/02/2002', '13:00','19:00'); 

select t1.* 
from @t t1 
    inner join @t t2 
     on(t1.RowID <> t2.RowID  -- If you don't have a unique ID for your rows, you will need to specify all columns so as no to match on the same row. 
      and t1.ID = t2.ID 
      and t1.DateValue = t2.DateValue 
      and t1.StartTime <= t2.EndTime 
      and t1.EndTime >= t2.StartTime 
      ) 
order by t1.RowID 
0

如果使用SQL Server 2012中,你可以試試下面的腳本:

declare @roster table (StaffID int,[Date] date,[Start] Time,[End] Time); 
insert into @roster values 
(1, '01/01/2000', '9:00','11:00') 
,(1, '01/01/2000', '8:00','12:00') 
,(2, '01/01/2000', '10:00','14:00') 
,(2, '01/01/2000', '8:00','9:00' ) 
,(3, '01/01/2000', '14:00','18:00') 
,(3, '02/02/2002', '13:00','19:00'); 
SELECT t.StaffID,t.Date,t.Start,t.[End] FROM (
    SELECT y.StaffID,y.Date,y.Start,y.[End] 
    ,CASE WHEN y.[End] BETWEEN 
    LAG(y.Start)OVER(PARTITION BY y.StaffID,y.Date ORDER BY y.Start) AND LAG(y.[End])OVER(PARTITION BY y.StaffID,y.Date ORDER BY y.Start) THEN 1 ELSE 0 END 
    +CASE WHEN LEAD(y.[End])OVER(PARTITION BY y.StaffID,y.Date ORDER BY y.Start) BETWEEN y.Start AND y.[End] THEN 1 ELSE 0 END AS IsOverlap 
    ,COUNT (0)OVER(PARTITION BY y.StaffID,y.Date) AS cnt 
    FROM @roster AS y 
) t WHERE t.cnt>1 AND t.IsOverlap>0 
 
StaffID  Date  Start   End 
----------- ---------- ---------------- ---------------- 
1   2000-01-01 08:00:00.0000000 12:00:00.0000000 
1   2000-01-01 09:00:00.0000000 11:00:00.0000000