#sql #sql-server #tsql #sql-server-2012
#sql #sql-сервер #tsql #sql-server-2012
Вопрос:
У меня есть этот запрос:
if OBJECT_ID('tempdb..#tempA') is not null drop table #tempA
create table #tempA
(
tempid varchar(5),
tempdate smalldatetime
)
declare @loopdate smalldatetime
set @loopdate = '4/2/2013'
while (@loopdate <= '4/28/2013')
begin
--Purpose is to get IDs not in TableB for each date period
insert into #tempA (tempid, tempdate)
select storeid, @loopdate
from
(
select tableAid
from tableA
except
select tableBid
from tableB
where tableBdate = @loopdate
) as idget
set @loopdate = DATEADD(day, 1, @loopdate)
end
Есть ли способ создать цикл while на основе набора или это лучшее, что можно сделать?
РЕДАКТИРОВАТЬ: внесены изменения для корректности
РЕДАКТИРОВАТЬ: конечный результат
ID1 4/2/2014
ID2 4/2/2014
ID4 4/2/2014
ID2 4/3/2014
ID1 4/4/2014
ID5 4/4/2014
ID3 4/5/2014
Комментарии:
1. Я почти уверен, что это возможно, но не могли бы вы опубликовать пример ваших исходных данных и желаемого конечного результата?
2. Вы не вставляете значение для tempdate . Это не работает.
3. То, как вы это делаете, может быть лучшим способом. Решение set должно было бы сгенерировать этот набор дат.
Ответ №1:
Все еще цикл, но, возможно, немного более эффективный
while (@loopdate <= '4/28/2013')
begin
--Purpose is to get IDs not in TableB for each date period
insert into #tempA (tempid, tempdate)
select storeid, @loopdate
from
(
select tableAid
from tableA
left join tableB
on tableB.tableBid = tableA.tableAid
and tableB.tableBdate = @loopdate
where tableB.tableBid is null
) as idget
set @loopdate = DATEADD(day, 1, @loopdate)
end
Это требует некоторой работы, но может полностью помочь вам с набором
;WITH Days
as
(
SELECT cast('4/2/2013' AS datetime ) as 'Day'
UNION ALL
SELECT DATEADD(DAY, 1, Day) as 'Day'
FROM Days
where [DAY] <= '4/28/2013'
)
SELECT tableA.tableAid, Days.[Day]
from Days
left join tableB
on tableB.tableBdate = Days.[Day]
full join tableA
on tableB.tableBid = tableA.tableAid
where tableB.tableBid is null
Комментарии:
1. Действительно ли левое соединение более эффективно, чем исключение? Просто интересно.
2. @dotnetN00b может ли Except использовать индекс?
Ответ №2:
это зависит от того, есть ли в таблице not дата, если нет, то:
WITH DateList(DateDay) AS
(
SELECT CAST('2013-04-28' AS DATETIME)
UNION ALL
SELECT DATEADD(DAY, DATEDIFF(DAY,0,DATEADD(DAY, -1, DateDay)),0)
FROM DateList
WHERE DateDay between '2013-04-03' and '2013-04-28'
)
SELECT DISTINCT
tableAid
, DateDay
FROM DateList
cross join #tableA a
left join #tableB b
on tableAid = b.tableBid
and b.tableBdate = DateDay
where
b.tableBid is null
ORDER BY
DateDay ASC
Ответ №3:
insert into #tempA (tempid, tempdate)
select tableAid, tableAdate
from tableA
except
select tableBid,tableBdate
from tableB
where tableBdate >= '4/2/2013' and tableBdate <= '4/28/2013';
Ответ №4:
Вы можете включить диапазон дат в условное предложение, как показано ниже:
insert into #tempA (tempid, tempdate)
select tableAid
from tableA
except
select tableBid
from tableB
where tableBdate >= '4/2/2013' and tableBdate <= '4/28/2013';