SQL 查询两个日期之间的 select 个日期并排除两个日期之间的日期

SQL query to select dates between two dates and exclude dates between two dates

CREATE TABLE [dbo].[#temp1]
(
    [workDate] [datetime] NULL,
    [Id] [int] NULL,
) ON [PRIMARY]

INSERT INTO [dbo].[#temp1] 
VALUES ('12-01-2018', '11'), ('11-01-2018', '11'),
       ('10-01-2018', '11'), ('09-01-2018', '11')


CREATE TABLE [dbo].[#temp2]
(
    [workDate] [datetime] NULL,
    [Id] [int] NULL,
) ON [PRIMARY]

INSERT INTO [dbo].[#temp2] 
VALUES ('10-01-2018', '11'), ('09-01-2018', '11')

我有 2 个带日期的表格。

我想 select #temp1 的所有日期,但不计算 #temp2 的日期。

我用了,但没有得到想要的结果:

select A.workDate, A.Id
from [dbo].[#temp1] A
left join [dbo].[#temp2] B on A.Id = B.Id and A.workDate = B.workDate
where A.workDate between CAST('09.01.2018' as datetime) and CAST('12.01.2018' as datetime)
   or B.workDate not between CAST('09.01.2018' as datetime) and CAST('10.01.2018' as datetime)

我想要得到的结果:

workDate                   Id
-------------------------------
2018-01-12 00:00:00.000    11
2018-01-11 00:00:00.000    11

如何解决?

您编写查询的方式取决于表中的值。如果您已经知道要 select 的日期,您可以这样做:

where A.workDate between CAST('11.01.2018' as datetime) and CAST('12.01.2018' as datetime)

您可能想要的是 select 行,其中 left join 不匹配任何内容:

where B.workDate is null

A.Id=B.Id - 连接谓词中的这个条件在逻辑上是 wrong/makes 没有意义。你说的是比较日期 - Id 会在这里做什么? where 中的 OR 部分也是如此。

正如你所说的你的工作:从#temp1 开始的日期除了从#temp2 开始的日期 - 它可以是 "translated" 从英语到 SQL 几乎逐字逐句:

select A.workDate
from [dbo].[#temp1] A
where A.workDate between CAST('09.01.2018' as datetime) and CAST('12.01.2018' as datetime)

EXCEPT

select B.workData
from [dbo].[#temp2] B

"dates from #temp1 which do not exist in #temp2":

select A.workDate,A.Id
from [dbo].[#temp1] A
where A.workDate between CAST('09.01.2018' as datetime) and CAST('12.01.2018' as datetime)
  AND not exists(select 1 from [dbo].[#temp2] B WHERE B.workDate = A.workDate)

是的,就这么简单。

此外,您最好不要像这样投射日期:CAST('09.01.2018' as datetime)。 "Default" 日期 format 取决于设置,例如可以是

  • ddmmyy 德语
  • yymmdd ANSI
  • mmddyy美国

因此此转换可能会产生不同的日期(09 月 01 日或 01 月 09 日?) 使用 CONVERT(datetime, '09.01.2018', 104)。最好不要在查询中使用文字和魔术 strings/numbers - 将这些值放入变量中并像这样使用它们:

declare @date_begin date = CONVERT(date, '20180109', 112),
        @date_end date = CONVERT(date, '20180112', 112)

select A.workDate,A.Id
from [dbo].[#temp1] A
where A.workDate between @date_begin and @date_end
  AND not exists(select 1 from [dbo].[#temp2] B WHERE B.workDate = A.workDate)

如果您想要 select 具有两个日期值之间的日期且不在另一个 table 中的行,首先 select 使用 Between .. and 中的行Where 子句并使用 Not Exists.

省略属于其他 table 的日期

查询

select * from [dbo].[#temp1] as [t1]
where cast([workDate] as date) between '2018-09-01' and '2018-12-01'
and not exists(
    select 1 from [dbo].[#temp2] as [t2]
    where [t1].[workDate] = [t2].[workDate]
);

使用 and 条件更新您的查询,如下所示。并检查 B.workDate IS NULL 以便 [dbo].[#temp2] 中不存在该记录,然后它也会给出结果。

select A.workDate, A.Id
from [dbo].[#temp1] A
left join [dbo].[#temp2] B on A.Id = B.Id and A.workDate = B.workDate
where A.workDate between CAST('09.01.2018' as datetime) and CAST('12.01.2018' as datetime)
and (B.workDate IS NULL or B.workDate not between CAST('09.01.2018' as datetime) and CAST('10.01.2018' as datetime)