2016-09-21 2 views
-1

Предположим, у вас есть комната, которая 100sqft и вы хотите арендовать его с 1 августа по 31 августа Bookings Таблица схемыНахождение площади для диапазона дат

startdate|enddate|area|storageid 

вы следующие заказы

06-Aug|25-Aug|50|'abc' 
05-Aug|11-Aug|40|'xyz' 
18-Aug|23-Aug|30|'pqr' 
13-Aug|16-Aug|10|'qwe' 

Теперь кто-то запрашивает бронирование с 08 августа по 20 августа. Для этого диапазона дат максимальная доступная площадь - 10 кв. Футов (так как для дат 8,9,10 и 11 августа доступно только 10 кв. Футов).

Как бы вы создали эффективный SQL-запрос, чтобы получить это? Сейчас у меня очень грязный и неэффективный запрос, который дает неправильные результаты для некоторых случаев. Я не отправляю запрос, потому что он настолько грязный, что я не могу его объяснить сам.

Я не обязательно хочу его решать, используя только SQL. Если есть алгоритм, который может эффективно его решить, я бы извлек все данные из базы данных.

+2

Кто придумал, что способ сохранения данных даты? – Drew

+1

Сервер Mysql и sql - это два разных продукта. Pls удаляет ненужный тег продукта. Pls также включает то, что вы пробовали, и какие проблемы вы испытываете. На данный момент ваш вопрос больше нравится: дайте мне код. Есть много вопросов о SO вокруг резервирования. Вы проверили их? – Shadow

+0

@Drew: Игнорировать формат для дат. Я сохраняю даты в формате YYYY-MM-DD –

ответ

0

Кто-то удален SQL Server, но вот алгоритм:

DECLARE @startDate date = '2016-08-09'; 
DECLARE @endDate date = '2016-08-20'; 
DECLARE @totalArea decimal(19,2) = 100; 

WITH Src AS --Your source table 
(
    SELECT * FROM (VALUES 
    ('2016-08-06', '2016-08-25', 50, 'abc'), 
    ('2016-08-05', '2016-08-11', 40, 'xyz'), 
    ('2016-08-18','2016-08-23',30,'pqr'), 
    ('2016-08-13','2016-08-16',10,'qwe') 
    )T(startdate, enddate, area, storageid) 
), Nums AS --Numbers table 0..N, N must be greater than ranges calculated 
(
    SELECT 0 N 
    UNION ALL 
    SELECT N+1 N FROM Nums 
    WHERE N<DATEDIFF(DAY,@startDate,@endDate) 
) --Query 
--You can use total-maxUsed from range of days 
SELECT @totalArea-MAX(Used) FROM 
(
    --Group by day, sum all used areas 
    SELECT MidDate, SUM(Used) Used FROM 
    (
     --Join table with numbers, split every day, if room used, return area 
     SELECT DATEADD(DAY, N, @startDate) MidDate, CASE WHEN DATEADD(DAY, N, @startDate) BETWEEN startDate AND endDate THEN area END Used 
     FROM Src 
     CROSS APPLY Nums 
    ) T 
    GROUP BY MidDate 
) T 
+0

Что-то было ОП. Вероятно, это означает, что OP использует MySQL. – Shadow

+0

Я оставляю это, так как никаких других ответов не появилось, как алгоритмическое решение. Самая важная часть ниже '--Query' почти универсальна (кроме параметров и' DATEADD') –

Смежные вопросы