【发布时间】:2014-11-09 19:13:43
【问题描述】:
我有一个存储过程,现在我不是一个 DBA,所以我只是想知道这是否被认为是不好的做法,因为我有很多子查询具有基本相同的代码。
我应该改用表变量还是临时表?
我还必须将第二个查询重写为动态 SQL,因为我只想包含基于标志的联合,因此临时表在这里会更容易。
感谢大家的帮助
CREATE TABLE #Days(theDate datetime, DayAsString varchar(15))
CREATE TABLE #temp(id int identity(1,1),trip_date datetime, trip_return datetime, iteration int, weeknumber int)
IF @SpecificDay = 0
Begin
INSERT INTO #Days
SELECT [date] ,DATENAME(dw,[date])
FROM dbo.Calendar C
WHERE [Date] BETWEEN @start AND @end
AND C.[WkDName] in (select distinct siDay.Name
from schedule s
join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
join scheduleInterval sint on sim.scheduleIntervalID = sint.id
left join ScheduleItem siDay on sim.scheduleDayItemId = siDay.id
where s.schedule_id = @schedule_id
) --@wkDName
AND C.[Month] in (select distinct siMonth.Id
from schedule s
join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
join scheduleInterval sint on sim.scheduleIntervalID = sint.id
join ScheduleItem siMonth on sim.ScheduleMonthItemId = siMonth.id
where s.schedule_id = @schedule_id
) --@Month
AND C.[WkNo] in (select distinct sint.Id
from schedule s
join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
join scheduleInterval sint on sim.scheduleIntervalID = sint.id
join ScheduleItem siDay on sim.ScheduleDayItemId = siDay.Id
where s.schedule_id = @schedule_id) --@first last etc @occurence
Union all --include the last occurence of the month
SELECT [date] ,DATENAME(dw,[date])
FROM dbo.Calendar CLast
WHERE [Date] BETWEEN @start AND @end
AND CLast.[WkDName] in (select distinct siDay.Name
from schedule s
join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
join scheduleInterval sint on sim.scheduleIntervalID = sint.id
left join ScheduleItem siDay on sim.scheduleDayItemId = siDay.id
where s.schedule_id = @schedule_id
) --@wkDName
AND CLast.[Month] in (select distinct siMonth.Id
from schedule s
join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
join scheduleInterval sint on sim.scheduleIntervalID = sint.id
join ScheduleItem siMonth on sim.ScheduleMonthItemId = siMonth.id
where s.schedule_id = @schedule_id
) --@Month
AND CLast.[Last] = 1
END
ELSE --Specific date has been specified or last has been selected
INSERT INTO #Days
select distinct [date] ,DATENAME(dw,[date]) from
(
SELECT *
FROM dbo.Calendar C
WHERE [Date] BETWEEN @start AND @end
AND C.[Month] in (select distinct siMonth.Id
from schedule s
join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
join scheduleInterval sint on sim.scheduleIntervalID = sint.id
join ScheduleItem siMonth on sim.ScheduleMonthItemId = siMonth.id
where s.schedule_id = @schedule_id) --@Month
AND C.[Day] in (select distinct sint.Name
from schedule s
join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
join scheduleInterval sint on sim.scheduleIntervalID = sint.id
join ScheduleItem siMonth on sim.ScheduleMonthItemId = siMonth.id
where s.schedule_id = @schedule_id
AND sint.Name <> 'Last'
)
Union all --include the last occurence of the month IF LAST
SELECT *
FROM dbo.Calendar CLast
WHERE [Date] BETWEEN @start AND @end
AND CLast.[Month] in (select distinct siMonth.Id
from schedule s
join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
join scheduleInterval sint on sim.scheduleIntervalID = sint.id
join ScheduleItem siMonth on sim.ScheduleMonthItemId = siMonth.id
where s.schedule_id = @schedule_id
) --@Month
AND [Date] in (select LDtOfMo from dbo.Calendar
WHERE [Date] BETWEEN @start AND @end)
) as x
Begin
INSERT INTO #temp(trip_date,trip_return,iteration,weeknumber)
SELECT
theDate + CAST(@timeout AS DATETIME),theDate+ CAST(@timeback AS DATETIME),@WeekNo,DATEPART(wk, theDate+CAST(@timeout AS DATETIME))
FROM
#Days
END
【问题讨论】:
-
我倾向于使用相关的 EXISTS 子查询而不是 IN 子查询。您可能会尝试该方法以查看您获得不同且更优化的执行计划。在许多情况下,优化器足够聪明,可以为语义相同的查询生成最佳计划。
-
除了@Dan说的,最起码把
DISTINCT拿出来…… -
干杯@dan,我会尝试 EXISTS。我认为 EXISTS 会在发现事件后继续前进,而不是 IN 返回所有结果?
-
@Aaron 我认为使用 distinc 会提高性能,因为只有一个结果,还是会产生更多开销?我应该把它留给分析器来删除重复项吗?
-
它必须进行排序以消除重复 - 很可能会增加排序工作的成本不仅仅是以查询其余部分固有的任何有效排序顺序返回行 - 特别是因为这些行实际上并不是物化了。
标签: sql sql-server tsql subquery