SQL генерирует свободные слоты на лету из таблицы бронирований? - PullRequest
0 голосов
/ 16 ноября 2018

Я знаю, что в разделе 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 даты: start_day + end_day

Я подготовил скрипку здесь : https://www.db -fiddle.com / f / 6dm8q8UtmDkkkjExYfMEbx / 1

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Версия 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

https://www.db -fiddle.com / f / 6dm8q8UtmDkkkjExYfMEbx / 3

0 голосов
/ 16 ноября 2018

Вот решение ниже. Предполагается, что логика столбца идентификатора 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...