Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL日期范围查询-表比较_Sql_Sql Server_Tsql_Date_Gaps And Islands - Fatal编程技术网

SQL日期范围查询-表比较

SQL日期范围查询-表比较,sql,sql-server,tsql,date,gaps-and-islands,Sql,Sql Server,Tsql,Date,Gaps And Islands,我有两个SQL Server表,其中包含以下信息: 表t\U场馆: 场馆id是唯一的 venue_id | start_date | end_date 1 | 01/01/2014 | 02/01/2014 2 | 05/01/2014 | 05/01/2014 3 | 09/01/2014 | 15/01/2014 4 | 20/01/2014 | 30/01/2014 表t\u venueuse

我有两个SQL Server表,其中包含以下信息:

t\U场馆

场馆id
是唯一的

venue_id  |  start_date  |  end_date
       1  |  01/01/2014  |  02/01/2014
       2  |  05/01/2014  |  05/01/2014
       3  |  09/01/2014  |  15/01/2014
       4  |  20/01/2014  |  30/01/2014
t\u venueuser

场馆id
不唯一

venue_id  |  start_date  |  end_date
       1  |  02/01/2014  |  02/01/2014
       2  |  05/01/2014  |  05/01/2014
       3  |  09/01/2014  |  10/01/2014
       4  |  23/01/2014  |  25/01/2014
从这两个表中,我需要找到尚未为每个范围选择的日期,因此输出如下所示:

venue_id  |  start_date  |  end_date
       1  |  01/01/2014  |  01/01/2014
       3  |  11/01/2014  |  15/01/2014
       4  |  20/01/2014  |  22/01/2014
       4  |  26/01/2014  |  30/01/2014

我可以比较这两个表,并使用“except”从
t\u ventions
获取要显示在我的查询中的日期范围,但我无法获取生成未选择日期的查询。任何帮助都将不胜感激。

这是一个完整的破解,但它给出了您所需的结果,我仅根据您提供的数据进行了测试,因此可能会有更大的数据集

一般来说,您在这里要解决的是间隙和孤岛问题的变化,这是(简要地)缺少某些项的序列。缺少的项目称为间隙,现有项目称为孤岛。如果您想大致了解此问题,请查看以下几篇文章:

代码:

;with dates as
(
    SELECT  vdates.venue_id,    
            vdates.vdate
    FROM  ( SELECT DATEADD(d,sv.number,v.start_date) vdate
                 , v.venue_id
            FROM t_venues v
            INNER JOIN master..spt_values sv 
                ON sv.type='P'
               AND sv.number BETWEEN 0 AND datediff(d, v.start_date, v.end_date)) vdates
    LEFT JOIN t_venueuser vu
        ON vdates.vdate >= vu.start_date
       AND vdates.vdate <= vu.end_date
       AND vdates.venue_id = vu.venue_id
    WHERE ISNULL(vu.venue_id,-1) = -1
)
SELECT venue_id, ISNULL([1],[2]) StartDate, [2] EndDate
FROM   (SELECT venue_id, rDate, ROW_NUMBER() OVER (PARTITION BY venue_id, DateType ORDER BY rDate) AS rType, DateType as dType
        FROM(   SELECT d1.venue_id
                      ,d1.vdate AS rDate
                      ,'1' AS DateType
                FROM dates AS d1    
                LEFT JOIN dates AS d0
                    ON DATEADD(d,-1,d1.vdate) = d0.vdate
                LEFT JOIN dates AS d2       
                    ON DATEADD(d,1,d1.vdate) = d2.vdate
                WHERE CASE ISNULL(d2.vdate, '01 Jan 1753') WHEN '01 Jan 1753' THEN '2' ELSE '1' END = 1
                AND ISNULL(d0.vdate, '01 Jan 1753') = '01 Jan 1753'
                UNION 
                SELECT d1.venue_id
                      ,ISNULL(d2.vdate,d1.vdate)
                      ,'2'
                FROM dates AS d1    
                LEFT JOIN dates AS d2       
                    ON DATEADD(d,1,d1.vdate) = d2.vdate
                WHERE CASE ISNULL(d2.vdate, '01 Jan 1753') WHEN '01 Jan 1753' THEN '2' ELSE '1' END = 2
            ) res
        ) src
PIVOT   (MIN (rDate)
        FOR dType IN
        ( [1], [2] )
        ) AS pvt
venue_id    StartDate   EndDate
1           2014-01-01  2014-01-01
3           2014-01-11  2014-01-15
4           2014-01-20  2014-01-22
4           2014-01-26  2014-01-30
日历桌! 另一个完美的日历表候选人。如果你懒得去寻找一个

设置数据 询问 解释 我们的日历表包含每个日期的条目

我们加入我们的
t\u场馆
(如果您有选择,请取消
t\u
前缀!),每天在
开始日期
结束日期
之间返回。仅此连接的
vention\u id=4
输出示例:

venue_id    the_date
----------- -----------------------
4           2014-01-20 00:00:00.000
4           2014-01-21 00:00:00.000
4           2014-01-22 00:00:00.000
4           2014-01-23 00:00:00.000
4           2014-01-24 00:00:00.000
4           2014-01-25 00:00:00.000
4           2014-01-26 00:00:00.000
4           2014-01-27 00:00:00.000
4           2014-01-28 00:00:00.000
4           2014-01-29 00:00:00.000
4           2014-01-30 00:00:00.000

(11 row(s) affected)
现在我们每天有一行,我们[outer]加入我们的
t\u venueuser
表。我们加入的方式与之前基本相同,但有一个额外的转折点:我们也需要基于
场馆id
加入

场馆\u id=4运行此操作将得到以下结果:

venue_id    the_date                t_venueuser_venue_id
----------- ----------------------- --------------------
4           2014-01-20 00:00:00.000 NULL
4           2014-01-21 00:00:00.000 NULL
4           2014-01-22 00:00:00.000 NULL
4           2014-01-23 00:00:00.000 4
4           2014-01-24 00:00:00.000 4
4           2014-01-25 00:00:00.000 4
4           2014-01-26 00:00:00.000 NULL
4           2014-01-27 00:00:00.000 NULL
4           2014-01-28 00:00:00.000 NULL
4           2014-01-29 00:00:00.000 NULL
4           2014-01-30 00:00:00.000 NULL

(11 row(s) affected)
查看如何为没有
t\u venueuser
记录的行设置
NULL
值。天才,不是吗<代码>;-)

因此,在我的第一个查询中,我给了您一个快速的CASE语句,它显示了可用性(1=可用,0=不可用)。这仅用于说明,但可能对您有用


然后,您可以将查询包装起来,然后在此计算列上应用一个额外的筛选器,或者只需在:
where t_venueuser.venue_id为NULL
中添加一个where子句,这将执行相同的操作。

结果中的venue 3行不应该是2014年1月11日到2014年1月15日吗?是的,谢谢-好位置!如果答案有帮助的话,别忘了将其标记为已接受。这真是太棒了。非常感谢。我在一个更大的数据集上运行了它,我能找到的唯一问题是,当事件已经过去,并且在事件开始时有可用的日期时,它只显示1天?例如:场馆为2014年9月1日至2014年9月10日,且场馆用户已登记为2014年9月5日至2014年9月10日,输出将显示2014年9月4日至2014年9月4日?我正在玩它,看看能不能修好它@samhankin我很高兴我们能提供帮助,如果还有什么我们可以帮助的,请告诉我们。感谢您抽出时间来帮助我们!我已经尝试了这两种解决方案,它们都非常棒-谢谢!我学了很多@萨姆汉金很高兴我能帮上忙。如果您对代码有任何疑问,请询问,我将更新我的答案以填补任何空白:)
venue_id    the_date                is_available
----------- ----------------------- ------------
1           2014-01-01 00:00:00.000 1
1           2014-01-02 00:00:00.000 0
2           2014-01-05 00:00:00.000 0
3           2014-01-09 00:00:00.000 0
3           2014-01-10 00:00:00.000 0
3           2014-01-11 00:00:00.000 1
3           2014-01-12 00:00:00.000 1
3           2014-01-13 00:00:00.000 1
3           2014-01-14 00:00:00.000 1
3           2014-01-15 00:00:00.000 1
4           2014-01-20 00:00:00.000 1
4           2014-01-21 00:00:00.000 1
4           2014-01-22 00:00:00.000 1
4           2014-01-23 00:00:00.000 0
4           2014-01-24 00:00:00.000 0
4           2014-01-25 00:00:00.000 0
4           2014-01-26 00:00:00.000 1
4           2014-01-27 00:00:00.000 1
4           2014-01-28 00:00:00.000 1
4           2014-01-29 00:00:00.000 1
4           2014-01-30 00:00:00.000 1

(21 row(s) affected)
venue_id    the_date
----------- -----------------------
4           2014-01-20 00:00:00.000
4           2014-01-21 00:00:00.000
4           2014-01-22 00:00:00.000
4           2014-01-23 00:00:00.000
4           2014-01-24 00:00:00.000
4           2014-01-25 00:00:00.000
4           2014-01-26 00:00:00.000
4           2014-01-27 00:00:00.000
4           2014-01-28 00:00:00.000
4           2014-01-29 00:00:00.000
4           2014-01-30 00:00:00.000

(11 row(s) affected)
venue_id    the_date                t_venueuser_venue_id
----------- ----------------------- --------------------
4           2014-01-20 00:00:00.000 NULL
4           2014-01-21 00:00:00.000 NULL
4           2014-01-22 00:00:00.000 NULL
4           2014-01-23 00:00:00.000 4
4           2014-01-24 00:00:00.000 4
4           2014-01-25 00:00:00.000 4
4           2014-01-26 00:00:00.000 NULL
4           2014-01-27 00:00:00.000 NULL
4           2014-01-28 00:00:00.000 NULL
4           2014-01-29 00:00:00.000 NULL
4           2014-01-30 00:00:00.000 NULL

(11 row(s) affected)