Как я могу использовать предложение между, чтобы отфильтровать 2 различных поля даты и времени - PullRequest
0 голосов
/ 07 мая 2018

Мне нужно внедрить систему бронирования залов, и есть требование, чтобы получить бесплатные залы на основе забронированных FromDateTime до ToDateTime

Стол заказов

HallID       FromDateTime            ToDateTime
1        2018-01-01 03:00:00    2018-01-01 05:00:00
2        2018-01-01 06:30:00    2018-01-01 12:00:00
3        2018-01-01 13:00:00    2018-01-01 15:15:00

Пользователь должен иметь возможность ввести от FromDateTime до ToDateTime, чтобы проверить, есть ли запись в таблице заказов. Если существует, зал не доступен для бронирования.

Тестовые сценарии: входы

    FromDateTime           ToDateTime           Result
2018-01-01 03:00:00    2018-01-01 05:00:00 : Hall not available
2018-01-01 08:45:00    2018-01-01 10:30:00 : Hall not available (This time is between Hall ID 2s booking time)
2018-01-01 15:30:00    2018-01-01 18:00:00 : Hall available

Вопрос

Можно ли использовать в этом сценарии предложение между FromDateTime и ToDateTime для решения этой проблемы? Я не смог найти способ использовать между ними, поэтому я использовал метод ниже. Но его стоимость очень высока.

-- Selecting all the records related to perticular product(hall) in to a temp table.

DECLARE @TempOrderDateTime TABLE (FromDateTime DATETIME,ToDateTime DATETIME)
INSERT INTO @TempOrderDateTime
SELECT FromDateTime,ToDateTime
FROM [Order].[Order]
WHERE ProductID = 7

Разделение каждой записи на 1-часовые зелья и сохранение внутри временной таблицы. Это создает другую проблему.

Проблема в том, что если я использую 1-часовой сегмент, алгоритм не сможет работать с записями, которые имеют минуты в FromDateTime или ToDateTime

DECLARE @ProdTimes TABLE (Dates DATETIME)
DECLARE @PRowCount INT = (SELECT COUNT(*) FROM @TempOrderDateTime)
WHILE(@PRowCount>0)
BEGIN
DECLARE @TopFromDateTime DATETIME = (SELECT TOP(1)FromDateTime FROM 
@TempOrderDateTime)
DECLARE @TopToDateTime DATETIME = (SELECT TOP(1)ToDateTime FROM @TempOrderDateTime)    
;WITH Dates_CTE 
     AS (SELECT @TopFromDateTime AS Dates
         UNION ALL
         SELECT DATEADD(HOUR, 1, Dates)
         FROM   Dates_CTE
         WHERE  Dates < @TopToDateTime)
INSERT INTO @ProdTimes
SELECT Dates
FROM   Dates_CTE AS t
OPTION (MAXRECURSION 0);
         DELETE TOP(1) FROM @TempOrderDateTime 
         SET @PRowCount = (SELECT COUNT(*) FROM @TempOrderDateTime)
END

Здесь я даюFromDateTime и ToDateTime в качестве входных данных для проверки доступности.

DECLARE @FromDateTime DATETIME  = '2018-06-01 12:00:00.000'
DECLARE @ToDateTime DATETIME = '2018-06-01 14:00:00.000'
DECLARE @PTimes TABLE (Dates DateTime)  

;WITH Dates_CTE
     AS (SELECT @FromDateTime AS Dates
         UNION ALL
         SELECT DATEADD(HOUR, 1, Dates)
         FROM   Dates_CTE
         WHERE  Dates < @ToDateTime)
INSERT INTO @PTimes
SELECT *
FROM   Dates_CTE AS t
OPTION (MAXRECURSION 0);

DELETE FROM @PTimes WHERE Dates = @FromDateTime OR Dates = @ToDateTime

Наконец, выполните следующую операцию для сопоставления таблиц. Если записи не найдены, зал доступен для бронирования.

SELECT * FROM @PTimes p
WHERE EXISTS (SELECT 1 FROM @ProdTimes pt WHERE p.Dates = pt.Dates)

Мой подход в настоящее время применим. Но главный недостаток -

  • Если записи таблицы заказов содержат запись с минутами, алгоритм не будет работать. Потому что он отфильтровывает только 1-часовые зелья.
  • Стоимость очень высокая.

Пожалуйста, предложите мне правильный способ решения этой проблемы.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 07 мая 2018

Вы не хотите between. Логика:

select h.*
from halls h
where not exists (select 1
                  from orders o
                  where o.hallid = h.hallid and
                        o.FromDateTime < @ToDateTime and
                        o.ToDateTime > @FromDateTime
                 );

Я почти уверен, что это самое простое решение вашей проблемы. Обратите внимание, что определение перекрытия вообще не включает between. Два периода перекрываются, если один начинается до второго конца и заканчивается после начала второго.

0 голосов
/ 07 мая 2018

Я надеюсь, что понял, но если не стесняйтесь, прокомментируйте это.
Допустим, пользователь собирается отправить запрос на 2018-01-01-04:30:00

ДАТА Таблица:

   FromDateTime           ToDateTime           Result
2018-01-01 03:00:00    2018-01-01 05:00:00 : Hall not available
2018-01-01 08:45:00    2018-01-01 10:30:00 : Hall not available (This time is between Hall ID 2s booking time)
2018-01-01 15:30:00    2018-01-01 18:00:00 : Hall available

Ваш чек должен выглядеть примерно так:

DECLARE @UserDateRequest DATETIME = '2018-01-01-04:30:00'
SELECT @UserDateRequest,
       Result
FROM DATES
WHERE @UserDateRequests BETWEEN @FromDateTime AND @ToDateTime
...