2012-10-10 32 views
0

我有一个SQL查询,它会记录一个日期并报告过去7天内已扫描到某个软件仓库但未在给定日期扫描的托盘数量。这需要大约一秒钟的时间。我需要在过去14天内报告此数字(使用SSRS报告)。然而 - 当我创建一个CTE或临时表来生成报告日期时,而不是上升到10秒(约10个日期),它会增加到3分钟以上!当使用CTE或温度表时,SQL Server查询速度较慢

请指教。

这里的单日报表:

DECLARE @back integer 
SET @back = 7 
Declare @testDate DateTime 
SET @testDate = '2012-10-09' 
--opening balance query 
select count(p.PalletID) as Opening_Balance 
FROM [POSTALE].[dbo].[Pallet] p 
join [POSTALE].[dbo].[Tracking] t on t.PalletID = p.PalletID 
--scan was before indicated day 
where CAST(DateAdd(hour, -6, t.TrackDateTime) as DATE) <= @testDate 
--scan was after number of days to look back 
and CAST(DateAdd(hour, -6, t.TrackDateTime) as DATE) >= dateadd(day, 0 - @back, @testDate) 
--scanned into hub (get only the earliest occurence) 
and t.TrackingID = (select top 1 tr.TrackingID from [POSTALE].[dbo].[Tracking] tr 
       where tr.TrackCode in ('SCAN OFF TRUNK HUB', 'DAYS') 
       and tr.PalletID = t.PalletID order by tr.TrackingID) 
--not scanned out of hub by the indicated day 
and (select count(tr.TrackingID) from [POSTALE].[dbo].[Tracking] tr where t.PalletID = tr.PalletID and 
    CAST(DateAdd(hour, -6, tr.TrackDateTime) as DATE) <= @testDate and tr.TrackCode in 
    ('SCAN ONTO TRUNK DEPOT', 'SCAN OFF TRUNK DEPOT', 'SECURITY SCAN AT DEPOT', 'SCAN OFF TRUNK DEPOT', 'SCANNER BROKEN', 
    'SCAN ON DEPOT VEHICLE', 'POD ADDED','NO POD ADDED')) = 0 

下面的代码的CTE加入吧:

DECLARE @back integer 
SET @back = 7 
declare @start_date as date; 
set @start_date = cast(getdate() - 14 as date); 
declare @end_date as date; 
set @end_date = cast(getdate() as date); 
WITH DateList AS 
(
    SELECT @start_date AS start_date 
    UNION ALL 
    SELECT DATEADD(DAY, 1, start_date) 
    FROM DateList 
    WHERE DATEADD(DAY, 1, start_date) < @end_date 
) 
SELECT 
    (select count(p.PalletID) as Opening_Balance 
... 
,datediff(DAY, d.start_date, getdate()) as daysBack 
from DateList d 
order by d.start_date 

..和这里的临时表的版本:

DECLARE @back integer 
SET @back = 7 
--hours into day that get pushed back to previous day 
DECLARE @dayStart integer 
set @dayStart = 12 
--today + 12 hours as datetime 
Declare @date12 as datetime 
set @date12 = DateAdd(hour, @dayStart, cast(cast(getdate() as date) as datetime)) 
--temporary table to create list of dates to report on 
DECLARE @DateList TABLE(
     DayDate DateTime 
) 
insert into @DateList (DayDate) Select DateAdd(day, - 14, @date12) where datepart(weekday, getdate() - 14) <> 7 and datepart(weekday, getdate() - 14) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 13, @date12) where datepart(weekday, getdate() - 13) <> 7 and datepart(weekday, getdate() - 13) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 12, @date12) where datepart(weekday, getdate() - 12) <> 7 and datepart(weekday, getdate() - 12) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 11, @date12) where datepart(weekday, getdate() - 11) <> 7 and datepart(weekday, getdate() - 11) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 10, @date12) where datepart(weekday, getdate() - 10) <> 7 and datepart(weekday, getdate() - 10) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 9, @date12) where datepart(weekday, getdate() - 9) <> 7 and datepart(weekday, getdate() - 9) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 8, @date12) where datepart(weekday, getdate() - 8) <> 7 and datepart(weekday, getdate() - 8) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 7, @date12) where datepart(weekday, getdate() - 7) <> 7 and datepart(weekday, getdate() - 7) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 6, @date12) where datepart(weekday, getdate() - 6) <> 7 and datepart(weekday, getdate() - 6) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 5, @date12) where datepart(weekday, getdate() - 5) <> 7 and datepart(weekday, getdate() - 5) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 4, @date12) where datepart(weekday, getdate() - 4) <> 7 and datepart(weekday, getdate() - 4) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 3, @date12) where datepart(weekday, getdate() - 3) <> 7 and datepart(weekday, getdate() - 3) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 2, @date12) where datepart(weekday, getdate() - 2) <> 7 and datepart(weekday, getdate() - 2) <> 1 
insert into @DateList (DayDate) Select DateAdd(day, - 1, @date12) where datepart(weekday, getdate() - 1) <> 7 and datepart(weekday, getdate() - 1) <> 1 
SELECT 
    (select count(p.PalletID) as Opening_Balance 
... 
,datediff(DAY, d.DayDate, getdate()) as daysBack 
from @DateList d 
order by d.DayDate 

回答

2

你没有描述你的索引,这显然是一个巨大的因素,但我注意到的一件事是你的WHERE子句元素不是sargable,可能是。

例如,尝试改变:

where CAST(DateAdd(hour, -6, t.TrackDateTime) as DATE) <= @testDate 

where t.TrackDateTime < dateadd(hour, 6, dateadd(day, 1, @testDate)) 

你需要做类似的事情与这条线:

and CAST(DateAdd(hour, -6, t.TrackDateTime) as DATE) >= dateadd(day, 0 - @back, @testDate) 
+0

红 - 感谢有帮助回应,并为延迟回应道歉。我已经尝试删除所有CAST语句,以最大限度地利用索引(我不允许修改数据库本身),但它恐怕没有任何区别。神秘的问题是,查询对单个日期(大约1秒)运行良好,但是当与临时表或CTE结合使用10天时,它需要延长(4-5分钟)一个数量级。 –

+0

这不仅仅是CAST,DATEADD也是一个问题。因此,在CTE内部,确保'='左边的列没有包含任何函数,并描述了索引。 – RedFilter

+0

我认为它必须与服务器上的内存限制(强制使用虚拟内存)有关。然而,使用你的提示,并使用新的CTE来限制嵌套子查询中的搜索量,我已经把时间缩短到了1分钟,我认为这是可以接受的 - 感谢你的建议。 –