查找可用于日期范围的区域

时间:2016-09-21 05:33:52

标签: mysql sql algorithm

假设您有一个100平方英尺的房间,并且您想在8月1日至8月31日期间租用它。 预订表架构

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'

现在有人要求在8月8日至8月20日期间预订。对于这个日期范围,可用的最大面积是10平方英尺(因为,对于8月8日,10日和10月11日,只有10平方英尺可用。)

如何创建有效的SQL查询来获取此信息?现在我的查询非常混乱和低效,在某些情况下会产生错误的结果。我没有发布查询,因为它太乱了,我自己无法解释。

我不一定只想使用SQL来解决它。如果有一种算法可以有效地解决它,我会从数据库中提取所有数据。

1 个答案:

答案 0 :(得分: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