我知道php部分有很多预订问题。 当我告诉您我尝试了其中大多数功能时,请相信我,至少是那些看起来兼容的功能。所以让我解释一下。
我有这个约会表
ID | day | start | end |
----------------------------------
1 | 01-01-2018 | 09:00 | 10:00 |
2 | 01-01-2018 | 10:00 | 13:00 |
3 | 02-01-2018 | 12:00 | 15:00 |
4 | 02-01-2018 | 18:00 | 19:30 |
我想知道,使用sql可以获取空时隙吗?结果应该类似于:
day | start | end
---------------------------
01-01-2018 | 00:00 | 09:00
01-01-2018 | 13:00 | 23:59
02-01-2018 | 00:00 | 12:00
02-01-2018 | 15:00 | 18:00
02-01-2018 | 19:30 | 23:59
查询应包含2个日期:开始日期+结束日期
我在这里准备了小提琴:https://www.db-fiddle.com/f/6dm8q8UtmDkkkjExYfMEbx/1
答案 0 :(得分:1)
MSSQL版本
WITH X AS
(
SELECT ROW_NUMBER() OVER (ORDER BY Day, Start)sq, [Day], [Start], [End]
FROM (
SELECT [Day], [Start], [End]
FROM [appointments]
UNION
SELECT Day, '00:00', '00:00'
FROM [appointments]
UNION
SELECT Day, '23:59', '23:59'
FROM [appointments]
) T1
)
SELECT A.Day, A.[End] AS Start, b.[Start] AS End
FROM x A
JOIN x B
ON A.sq = B.sq -1
AND A.[Day] = B.[Day]
AND A.[End] <> b.[Start]
Mysql 5.7版本
SET @RowNumber = 0;
CREATE TABLE cte
SELECT (@RowNumber := @RowNumber+1) AS Rownumber, Day, Start, End
FROM (
SELECT Day, Start, End
FROM booking
UNION
SELECT Day, '00:00', '00:00'
FROM booking
UNION
SELECT Day, '23:59', '23:59'
FROM booking
) T1
ORDER BY day ASC, Start ASC
;
SELECT A.Day, A.End AS Start, B.Start AS End
FROM cte A
JOIN cte B
ON A.Rownumber = B.Rownumber -1
AND A.Day = B.Day
AND A.End <> B.Start
ORDER BY A.Day asc, A.End asc
将添加一个小提琴来演示 https://www.db-fiddle.com/f/6dm8q8UtmDkkkjExYfMEbx/2
Mysql 5.7,包括没有预订的天数
SET @RowNumber = 0;
CREATE TABLE cte
SELECT (@RowNumber := @RowNumber+1) AS Rownumber, Day, Start, End
FROM (
SELECT Day, Start, End
FROM booking
UNION
SELECT Day, '00:00', '00:00'
FROM booking
UNION
SELECT Day, '23:59', '23:59'
FROM booking
) T1
ORDER BY day ASC, Start ASC
;
SELECT DAY, Start, End
FROM(
SELECT A.Day, A.End AS Start, B.Start AS End
FROM cte A
JOIN cte B
ON A.Rownumber = B.Rownumber -1
AND A.Day = B.Day
AND A.End <> B.Start
UNION
SELECT DATE_ADD(A.Day, INTERVAL 1 DAY) AS Day, B.Start AS Start, A.End AS End
FROM cte A
JOIN cte B
ON A.Rownumber = B.Rownumber -1
AND A.Day <> B.Day
)Result
ORDER BY Day ASC, Start ASC
答案 1 :(得分:0)
这是下面的解决方案。假设ID列的逻辑为identity(1,1)
,否则请首先为每个列生成row_number()
。语法可能与MySql不匹配,但是如果您愿意,您将获得逻辑并应用相同的逻辑。
CREATE TABLE #result (
[day] date NOT NULL,
[start] time NOT NULL,
[end] time NOT NULL
)
declare @maxid int = (select max(id) from #booking), @counter int = 1, @day date
declare @tempStart time = '00:00', @currentStart time ='00:00'
declare @tempDay date = (select TOP 1 [day] from #booking)
while @counter <= @maxid
begin
set @currentStart = (select start from #booking where id=@counter)
set @day = (select [day] from #booking where id=@counter)
if (@day > DATEADD(day,1,@tempDay))
begin
insert into #result values (DATEADD(day,1,@tempDay),'00:00', '23:00')
set @tempDay = @day
end
if(@tempStart < @currentStart)
begin
insert into #result values (@day, @tempStart, @currentStart)
end
if(@counter = @maxid and @tempStart <> '23:59')
begin
insert into #result values (@day, (select [end] from #booking where id=@counter), '23:59')
end
set @tempStart = (select [end] from #booking where id=@counter)
set @counter = @counter + 1
end
select * from #result
SQL Server示例:https://rextester.com/live/VBNJ34000