SQL Server 2014在where子句中使用DateAdd来过滤巨大的表

时间:2015-08-29 04:08:29

标签: sql sql-server where dateadd

我有两张表MeterMeterSpotMeter表有大约9000条记录,MeterSpot有大约7000万条记录。 MeterID列创建两个表之间的关系。这是表格设计的一部分:

  • Meter:MeterID int,ContractHour int等......

  • MeterSpot:MeterSpotID int,MeterID int,RecordStamp datetime,VolumeToday float等......

我在Meter.MeterIDMeterSpot.MeterSpotID上有一个聚集索引,在MeterSpot.RecordStampMeterSpot.MeterID上有非聚集索引。

现在,我需要查询这两个表中的数据,并获取MeterIDContractDateVolumeToday列,其中ContractDate位于给定日期范围之间。 ContractDate的计算方法是从ContractHour Meter表中减去RecordStamp MeterSpot表。

这就是我的尝试:

SELECT  
    M.MeterID, MS.VolumeToday,  
    DATEADD(hour, -(M.ContractHour), MS.RecordStamp) AS 'ContractDate'      
FROM 
    Meter AS M
INNER JOIN  
    MeterSpot AS MS ON M.MeterID = MS.MeterID   
WHERE 
    (DATEADD(hour, -(M.ContractHour), MS.RecordStamp)  
       BETWEEN @StartDate and @EndDate)

此查询需要数小时才能执行。我搜索的很少,发现当我在where子句中添加函数时,不考虑索引。

我在下面尝试过,对于较小的日期范围来说速度非常快。

WHERE MS.RecordStamp BETWEEN @StartDate AND @EndDate)

我尝试将ContractHour添加到@StartDate@EndDate,而不从RecordStamp中删除它。性能仍然相同。

问题:

  1. 如何过滤计算列中的数据?
  2. 我有更好的方法来完成我的任务吗?
  3. 使用这种巨大的桌子时,我应该遵循哪些好的做法?

1 个答案:

答案 0 :(得分:0)

您可以给出两次日期条件,一次以告知SQL如何利用其索引来加速查询,再次精确过滤掉您需要的行。 ContractHour有一些最大价值吗?如果是这样,那么你可以这样做:

select ... 
from Meter m 
join MeterSpot ms on m.MeterID = ms.MeterID
where 
     (ms.RecordStamp between @StartDateMinusMaxContractHour and @EndDate)
     and (dateadd(hour, -@m.ContractHour, ms.RecordStamp) between @StartDate and @EndDate)