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
Как это исправить?
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]
);
То, как вы написали запрос, зависит от значений в таблицах. Если вы уже знаете даты, которые хотите выбрать, вы можете просто сделать это:
where A.workDate between CAST('11.01.2018' as datetime) and CAST('12.01.2018' as datetime)
Вместо этого вы, вероятно, захотите, чтобы выбрать строки, где left join
ничего не соответствует:
where B.workDate is null
Обновите ваш запрос с условием 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)
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
ANSImmddyy
США
Так что это приведение может привести к различным датам (месяц 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)
Новые вопросы
sql
Язык структурированных запросов (SQL) - это язык запросов к базам данных. Вопросы должны включать примеры кода, структуру таблицы, примеры данных и тег для используемой реализации СУБД (например, MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 и т. Д.). Если ваш вопрос относится исключительно к конкретной СУБД (использует определенные расширения / функции), используйте вместо этого тег этой СУБД. Ответы на вопросы, помеченные SQL, должны использовать стандарт ISO / IEC SQL.