获取另一个表中不包括时间间隔的数据

Hin*_*man 4 sql-server t-sql

我有两张桌子,MessageBlockUser

Message

ID | Message | DateCreated 
1  | M1      | 2017-09-20 13:00:00
2  | M2      | 2017-09-20 14:00:00 
3  | M3      | 2017-09-21 13:00:00
4  | M3      | 2017-09-22 13:00:00
5  | M3      | 2017-09-23 13:00:00
6  | M3      | 2017-09-24 13:00:00
7  | M3      | 2017-09-25 13:00:00
Run Code Online (Sandbox Code Playgroud)

BlockUser

BlockStartDate       | BlockEndDate
2017-09-21 13:00:00  | 2017-09-22 13:00:00
2017-09-24 13:00:00  | 2017-09-24 14:00:00
Run Code Online (Sandbox Code Playgroud)

现在我想要Message排除那些与BlockUser. 所以对于我的例子,结果应该是:

ID | Message | DateCreated 
1  | M1      | 2017-09-20 13:00:00
2  | M2      | 2017-09-20 14:00:00 
5  | M3      | 2017-09-23 13:00:00
7  | M3      | 2017-09-25 13:00:00
Run Code Online (Sandbox Code Playgroud)

我尝试使用此查询,但没有奏效:

WITH CTE AS (
         SELECT BlockStartDate,BlockEndDate FROM BlockUser
         )
SELECT * FROM Message 
WHERE DateCreated NOT BETWEEN 
(SELECT BlockStartDate FROM CTE) 
AND 
(SELECT BlockEndDate  FROM CTE)
Run Code Online (Sandbox Code Playgroud)

它给了我这个错误:

子查询返回了 1 个以上的值。当子查询跟随 =、!=、<、<=、>、>= 或当子查询用作表达式时,这是不允许的。

And*_*y M 5

这是一个经典的反加入场景。您需要一个表中的行,但不包括与另一个表匹配的行。

在英语中,你可以这样写条件:

从中选择Message没有匹配行的每一行BlockUser

在 SQL 中,表达上述内容的一种方式是这样的:

SELECT
  *
FROM
  dbo.Message AS m
WHERE
  NOT EXISTS
  (
    SELECT
      *
    FROM
      dbo.BlockUser AS bu
    WHERE
      m.DateCreated >= bu.BlockStartDate
      AND m.DateCreated < bu.BlockEndDate
  )
;
Run Code Online (Sandbox Code Playgroud)