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 таблицы с датами.

Я хочу выбрать все даты из #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

Как это исправить?

2
abannobnesser 21 Авг 2018 в 07:45

4 ответа

Лучший ответ

Если вы хотите выбрать строки с датами между двумя значениями дат, которых нет в другой таблице, сначала выберите строки с помощью Between .. and в предложении Where и опустите даты, являющиеся частью другой таблицы, используя < сильный > Not Exists .

Запрос

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]
);
0
Ullas 21 Авг 2018 в 04:58

То, как вы написали запрос, зависит от значений в таблицах. Если вы уже знаете даты, которые хотите выбрать, вы можете просто сделать это:

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

Вместо этого вы, вероятно, захотите, чтобы выбрать строки, где left join ничего не соответствует:

where B.workDate is null
0
We Are All Monica 21 Авг 2018 в 04:51

Обновите ваш запрос с условием 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)
0
Karan 21 Авг 2018 в 05:00

A.Id=B.Id - это условие в предикате соединения логически неверно / не имеет смысла. Вы говорили о сравнении дат - для чего здесь Id? То же самое и с OR частью в where.

Как вы указали свою работу: даты из # temp1, за исключением дат из # temp2 - его можно «перевести» с английского на 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

Или "даты из # temp1, которых нет в # 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). Дата по умолчанию формат зависит от настроек и может быть, например,

  • ddmmyy немецкий
  • yymmdd ANSI
  • mmddyy США

Так что это приведение может привести к различным датам (месяц 09 день 01 или месяц 01 день 09?) Используйте CONVERT(datetime, '09.01.2018', 104). И лучше не использовать литералы и магические строки / числа в запросе - поместите эти значения в переменные и используйте их следующим образом:

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)
0
Ivan Starostin 21 Авг 2018 в 05:33
51941702