Tsql 比较日期的查询运行缓慢

Tsql 比较日期的查询运行缓慢,tsql,Tsql,谁能给点建议吗。下面的查询使用了大约200000条记录。我需要评估“DateTime”字段,以评估收入是否发生在正确的时间段内。我目前正在使用CASE语句来计算DateTime字段,它是一个绝对的pig,运行时间超过5分钟。有没有更快更有效的方法?请注意,变量@cur_date、@end_date、@prev_yr_qtr_start、@cur_date_yr_prev等均为字符串,r.pw_ship_date为DATETIME类型。所以本质上我是在比较r.pw_ship_date和字符串,即“

谁能给点建议吗。下面的查询使用了大约200000条记录。我需要评估“DateTime”字段,以评估收入是否发生在正确的时间段内。我目前正在使用CASE语句来计算DateTime字段,它是一个绝对的pig,运行时间超过5分钟。有没有更快更有效的方法?请注意,变量@cur_date、@end_date、@prev_yr_qtr_start、@cur_date_yr_prev等均为字符串,r.pw_ship_date为DATETIME类型。所以本质上我是在比较r.pw_ship_date和字符串,即“2017-01-01 00:00”

注意:当我为200000条记录添加“SELECT TOP(500)”时,运行此查询花费了4:00分钟,这将永远花费时间

提前谢谢

DECLARE @total TABLE
(
    acct_number VARCHAR(50),
    pro_nbr VARCHAR(50),
    sales_rep VARCHAR(50),
    bill_to_name VARCHAR(50),
    billing_addr1 VARCHAR(50),
    billing_addr2 VARCHAR(50),
    billing_city CHAR(50),
    billing_state CHAR(2),
    billing_zip CHAR(10),
    cur_month_bills INT,
    cur_month_rev DECIMAL(30, 6),
    cur_qtr_bills INT,
    cur_qtr_rev DECIMAL(30, 6),
    prev_yr_qtr_bills INT,
    prev_yr_qtr_rev DECIMAL(30, 6),
    cur_ytd_bills INT,
    cur_ytd_rev DECIMAL(30, 6),
    prev_ytd_bills INT
)


INSERT  INTO @total
SELECT  TOP(50000) f.acct_number ,
        r.pro_nbr ,
        r.sales_rep ,
        r.bill_to_name ,
        r.billing_addr1 ,
        r.billing_addr2 ,
        r.billing_city ,
        r.billing_state ,
        r.billing_zip ,
        'cur_month_bills' = MAX(( CASE WHEN r.pw_ship_date BETWEEN @cur_date AND @end_date THEN 1 ELSE 0 END )) ,
        'cur_month_rev' = MAX(ROUND(( CASE WHEN r.pw_ship_date BETWEEN @cur_date AND @end_date THEN f.tot_revenue ELSE 0 END ), 2)) ,
        'cur_qtr_bills' = MAX((CASE WHEN r.pw_ship_date BETWEEN @cur_date AND @end_date  THEN 1 ELSE 0 END )) ,
        'cur_qtr_rev' = MAX(ROUND(CASE WHEN r.pw_ship_date BETWEEN @cur_date AND @end_date THEN f.tot_revenue ELSE 0 END, 2)) ,
        'prev_yr_qtr_bills' = MAX(CASE WHEN r.pw_ship_date BETWEEN @prev_yr_qtr_start AND @cur_date_yr_prev THEN 1 ELSE 0 END ) ,
        'prev_yr_qtr_rev' = MAX(ROUND(CASE WHEN r.pw_ship_date BETWEEN @prev_yr_qtr_start AND @cur_date_yr_prev THEN f.tot_revenue ELSE 0 END , 2)) ,
        'cur_ytd_bills' = MAX(CASE WHEN r.pw_ship_date BETWEEN @first_day_cur_yr AND @end_date  THEN 1 ELSE 0 END ),
        'cur_ytd_rev' = MAX(ROUND(CASE WHEN r.pw_ship_date BETWEEN @first_day_cur_yr AND @end_date THEN f.tot_revenue ELSE 0 END , 2)) ,
        'prev_ytd_bills' = MAX(CASE WHEN r.pw_ship_date BETWEEN @first_day_prev_yr AND @end_date THEN 1    ELSE 0 END )
FROM    @summed f
INNER JOIN @raw r ON f.acct_number = r.acct_number AND f.pro_nbr = r.pro_nbr
GROUP BY f.acct_number ,
        r.pro_nbr ,
        r.sales_rep ,
        r.bill_to_name ,
        r.billing_addr1 ,
        r.billing_addr2 ,
        r.billing_city ,
        r.billing_state ,
        r.billing_zip;

将表变量
@raw
@summared
更改为临时表。表变量没有统计信息,在索引方面非常有限(只能有一个)。因此,SQL Server假定您的表变量只有一行(2012及更早版本)或100行(2014+)。这意味着您几乎肯定会得到一个糟糕的查询执行计划,这会毁了您

一旦您将
@raw
@summated
更改为
#raw
#summated
,在它们上建立索引-至少为外键(您要加入的字段)、
账号和
pro nbr
建立索引。创建聚集索引和/或主键可能是值得的,但这是您需要进行试验才能找到所需性能的东西

另一个影响性能的因素是将
datetime
s与字符串进行比较。这会导致类型转换,并且会严重拖累您。如果使用的是日期/时间,请使用适当的数据类型——而不是看起来像日期的字符串

如果这仍然不够快,请将
CASE
语句移出聚合函数

MAX(如果r.pw\u ship\u日期介于@cur\u日期和@end\u日期之间,则为1或0 end))


CASE
语句移动到填充
#raw.pw_ship_date
的查询中,这样在执行聚合时,您只需一直查看整数。

您应该将所有变量更改为
DateTime
。(有关详细信息,请参阅。)您还可以添加一个
where
子句,将处理的行范围限制为所需的最早和最晚日期,即
@第一天\上一年
可能是最小值,
@结束日期
可能是最大值。(我假设表中有超出该范围的数据。)提示:使用适当的软件(MySQL、Oracle、DB2等)和版本(例如
sql-server-2014
)标记数据库问题是很有帮助的。请说明如何创建表变量
@raw
@summated