我有以下SQL Server表。
mypage.*
考虑到[breakTable],我试图将[workingSchedule]中的时间间隔分成几行。我想要的结果是这样的:
CREATE TABLE workingSchedule
(
[workingDate] DATETIME NULL,
[openTime] TIME (7) NULL,
[closeTime] TIME (7) NULL
);
INSERT INTO workingSchedule
(workingDate, openTime, closeTime)
VALUES
('10/1/2015','9:00','17:00'),
('10/2/2015','9:00','17:00');
CREATE TABLE breakTable
(
[breakDate] DATETIME NULL,
[breakStart] TIME NULL,
[breakEnd] TIME NULL
);
INSERT INTO breakTable
(breakDate, breakStart, breakEnd)
VALUES
('10/1/2015','12:00','13:00'),
('10/1/2015','15:00','15:30'),
('10/2/2015','12:00','13:00');
我不确定是否应该使用CTE,函数或临时表。如果您能分享您的解决方案代码,我感谢您。当只有一次休息时,我能够分割时间间隔,但是当我达到每天多次休息时间时,我失败了。
答案 0 :(得分:0)
在这种情况下,我使用ROW_NUMBER(https://msdn.microsoft.com/en-us/library/ms186734.aspx)来帮助在一天内加入分组。我使用了UNION,但我认为你可以使用相同的连接逻辑,但是可以使用SELECT语句。
SELECT workingDate as [date], openTime as [Start], COALESCE(breakStart, closeTime) as [End]
FROM workingSchedule
LEFT JOIN (
SELECT breakDate, breakStart, breakEnd, ROW_NUMBER() OVER (PARTITION BY breakDate ORDER BY breakStart) AS ROWNUM
FROM breakTable
) as firstBreak ON workingSchedule.workingDate = firstBreak.breakDate AND firstBreak.ROWNUM = 1
UNION
SELECT breakStart.breakDate, breakStart.breakEnd, coalesce(breakEnd.breakStart, endTime.closeTime)
FROM (
SELECT breakDate, breakStart, breakEnd, ROW_NUMBER() OVER (PARTITION BY breakDate ORDER BY breakStart) AS ROWNUM
FROM breakTable
) as breakStart
LEFT JOIN (
SELECT breakDate, breakStart, breakEnd, ROW_NUMBER() OVER (PARTITION BY breakDate ORDER BY breakStart) AS ROWNUM
FROM breakTable
) as breakEnd ON breakStart.breakDate = breakEnd.breakDate AND breakStart.ROWNUM = breakEnd.ROWNUM - 1
LEFT JOIN (
SELECT workingDate, closeTime
FROM workingSchedule
) AS endTime ON breakStart.breakDate = endTime.workingDate
这里的想法是拉出开始时间,如果有的话,第一次休息。如果没有中断,COALESCE将取代closeTime。然后我们整天休息。最后,我们将closeTime加入到最后一个中断,再次使用COALESCE在没有" breakEnd.breakStart"时使用closeTime。
以下是其中的SQL Fiddler:http://sqlfiddle.com/#!6/5a4765/14
答案 1 :(得分:0)
以下是获得所需输出的查询
;WITH CTEOrderedBreaks
AS
(
SELECT row_number() over(partition by breakdate order by breakdate,breakstart asc) as rnob,
row_number() over(partition by breakdate order by breakdate,breakstart DESC) as rnobr,
breakdate,
breakstart,
breakend
from breakTable
),
CTESUMMARY
AS
(
SELECT WS.WORKINGDATE,WS.OPENTIME AS [START],COB.BREAKSTART AS [END]
FROM CTEOrderedBreaks COB INNER JOIN WORKINGSCHEDULE WS ON WS.WORKINGDATE = COB.breakdate
WHERE COB.RNOB=1
UNION ALL
SELECT COB1.BREAKDATE,COB1.BREAKEND AS [START],ISNULL(COB2.BREAKSTART,WS1.CLOSETIME)AS [END]
FROM CTEOrderedBreaks COB1
left JOIN CTEOrderedBreaks COB2 ON COB1.RNOB = COB2.RNOB-1
AND COB1.BREAKDATE = COB2.BREAKDATE
LEFT JOIN workingSchedule WS1 ON WS1.WORKINGDATE = COB1.BREAKDATE AND COB1.RNOBR=1
)
SELECT * FROM CTESUMMARY
ORDER BY WORKINGDATE,START
答案 2 :(得分:0)
You can try this
DECLARE @Tab TABLE
(
[Date] [datetime],
[Time] [time],
[Row] int
)
DECLARE @Tab2 TABLE
(
[Date] [datetime],
[Row] int
)
INSERT INTO @Tab2
SELECT DISTINCT(workingDate) , ROW_NUMBER() OVER(ORDER BY [workingDate])
FROM workingSchedule
DECLARE @Count int;
DECLARE @Num [int];
DECLARE @Dat [datetime];
SET @Num=1;
SET @Count=(SELECT count(*) FROM @Tab2 t)
WHILE @Num<=@Count
BEGIN
SET @Dat=(SELECT [Date] FROM @Tab2 t WHERE t.[Row]=@Num)
INSERT INTO @Tab
SELECT * , ROW_NUMBER() OVER( ORDER BY Cte4.breakStart) Number FROM (
SELECT * FROM(
SELECT Cte.breakDate, Cte.breakStart FROM
(SELECT * FROM breakTable
UNION ALL
SELECT * FROM workingSchedule
)Cte
WHERE Cte.breakDate=@Dat
)Cte2
UNION ALL
SELECT * FROM(
SELECT Cte.breakDate, Cte.breakEnd FROM
(SELECT * FROM breakTable
UNION ALL
SELECT * FROM workingSchedule
)Cte
WHERE Cte.breakDate=@Dat
)Cte3
)Cte4
ORDER BY Cte4.breakStart
SET @Num=@Num+1;
END
;WITH Cte AS
(
SELECT * FROM @Tab t
WHERE t.[Row]%2=0
),
Cte2 AS
(
SELECT * FROM @Tab t
WHERE t.[Row]%2=1
)
SELECT DISTINCT Cte.[Date],Cte2.[Time] AS Start, Cte.[Time] AS [End] FROM Cte
INNER JOIN
Cte2
ON
(Cte2.[Row]+1)=Cte.[Row]
答案 3 :(得分:0)
create table #answer
(workdate datetime null,
starttime time null,
endtime time null
)
declare cur cursor for (select workingDate,openTime,closeTime from workingSchedule)
declare @workingDate datetime,@openTime time,@closeTime time,@breakStart time,@breakEnd time,@breakEnd2 time,@counter int
set @counter = 0;
open cur
fetch cur into @workingDate,@openTime,@closeTime
while(@@FETCH_STATUS =0)
begin
declare cur2 cursor for select breakStart,breakEnd from breakTable where breakDate = @workingDate order by breakStart
open cur2
fetch cur2 into @breakStart,@breakEnd
set @counter = 1;
while(@@FETCH_STATUS=0)
begin
if(@counter = 1)
begin
insert into #answer values(@workingDate,@openTime,@breakStart)
end
else
begin
insert into #answer values(@workingDate,@breakEnd2,@breakStart)
end
set @breakEnd2 = @breakEnd
set @counter = @counter+1;
fetch cur2 into @breakStart,@breakEnd
end
close cur2
deallocate cur2
fetch cur into @workingDate,@openTime,@closeTime
end
close cur
deallocate cur
select * from #answer
drop table #answer
冲锋是:
2015-10-01 00:00:00.000 09:00:00.0000000 12:00:00.0000000
2015-10-01 00:00:00.000 13:00:00.0000000 15:00:00.0000000
2015-10-02 00:00:00.000 09:00:00.0000000 12:00:00.0000000
答案 4 :(得分:0)
;with cte as(
select *, row_number() over(partition by wd order by ot) rn
from
(select workingDate wd, openTime ot from workingSchedule
union
select workingDate, closeTime from workingSchedule
union
select breakDate, breakStart from breakTable
union
select breakDate, breakEnd from breakTable)t)
select c1.wd, c1.ot, c2.ot
from cte c1
join cte c2 on c1.wd = c2.wd and c1.rn + 1 = c2.rn and c1.rn % 2 = 1
order by c1.wd, c1.ot
想法是生成日期的有序时间,然后加入第二行的第一行,第四行的第三行......