我的T-SQL
查询执行得非常糟糕,以至于超时。罪魁祸首是这两个带嵌入式查询的嵌套CASE语句:
SELECT
CASE
WHEN b.month_type = (CASE
WHEN dbo.CURRENT_BUSINESSDAY(GETDATE()) >= 8 THEN 'Current Month BD2'
ELSE (CASE
WHEN dbo.CURRENT_BUSINESSDAY(GETDATE()) < 8 AND
(SELECT
MAX(b.cal_start_date)
FROM factbillingcollectionhistory a
JOIN dimdateperiod b
ON a.fiscal_month = b.fsc_period)
<> (SELECT
MAX(cal_start_date)
FROM dimdateperiod) THEN 'Current Reporting Month'
ELSE 'Current Month BD2'
END)
END) THEN a.BILLINGS_BUDGET
ELSE 0
END
AS BILLINGS_BUDGET,
CASE
WHEN b.month_type = (CASE
WHEN dbo.CURRENT_BUSINESSDAY(GETDATE()) >= 8 THEN 'Current Month BD2'
ELSE (CASE
WHEN dbo.CURRENT_BUSINESSDAY(GETDATE()) < 8 AND
(SELECT
MAX(b.cal_start_date)
FROM factbillingcollectionhistory a
JOIN dimdateperiod b
ON a.fiscal_month = b.fsc_period)
<> (SELECT
MAX(cal_start_date)
FROM dimdateperiod) THEN 'Current Reporting Month'
ELSE 'Current Month BD2'
END)
END) THEN a.COLLECTION_GOALS
ELSE 0
END
AS COLLECTION_GOALS
CURRENT_BUSINESSDAY
函数正如其描述的那样...识别报告期间的当前工作日。
CASE
的逻辑是根据我们在报告周期中的位置以及我们是否收到更新的目标文件来返回目标值。如果它还不是BD8,请检查我们是否收到了新文件(通过比较最大日期)。如果我们已收到它,请将该值返回到报表,否则返回上个月的值。如果它在BD8之后并且我们仍然没有新文件,它应该返回“0”,这将使我们的过程失败并告诉我们他们没有按时提供数据。
是否有更有效的方法来编写此逻辑,以防止查询超时?请记住,此脚本用于在表格模型中构建表,因此只有SELECT正在运行...没有变量声明或任何类型。
思想?
答案 0 :(得分:0)
由于COLLECTION_GOALS和BILLINGS_BUDGET中的大小写逻辑相同,我建议将逻辑移出内联子查询并移入主FROM子句,如下所示:
SELECT CASE WHEN b.month_type = z.month_type
THEN a.BILLINGS_BUDGET
ELSE 0
END AS BILLINGS_BUDGET,
CASE WHEN b.month_type = z.month_type
THEN a.COLLECTION_GOALS
ELSE 0
END AS COLLECTION_GOALS
FROM (SELECT CASE WHEN dbo.CURRENT_BUSINESSDAY(GETDATE()) >= 8
THEN 'Current Month BD2'
ELSE (CASE WHEN dbo.CURRENT_BUSINESSDAY(GETDATE()) < 8 AND
(SELECT max(b.cal_start_date)
FROM factbillingcollectionhistory a
JOIN dimdateperiod b
ON a.fiscal_month = b.fsc_period) <> (SELECT max(cal_start_date) FROM dimdateperiod)
THEN 'Current Reporting Month'
ELSE 'Current Month BD2'
END)
END month_type) z
CROSS JOIN
/*... Rest of query */
这应该导致每个查询评估一次,而不是查询返回的每一行两次。