我正在尝试合并一对几乎相同的查询,这些查询根据参数化变量(管道和完成(使用略有不同的WHERE
子句。
我正在努力找出对其进行编码以根据@ReportMode
变量查找日期范围或 NULL 的最佳方法。
首先,WHERE
条款基本上是:
DECLARE @ReportMode VARCHAR(20),
@ApplictnDate DATETIME;
SET @ApplictnDate =
CASE
WHEN @ReportMode = 'Completions' THEN '20160801 00:00:00'
WHEN @ReportMode = 'Pipeline' THEN '20170201 00:00:00'
END
SELECT
Id, AppDate, CompDate
FROM
TbTable
WHERE
AppDate > @ApplictnDate AND
CompDate BETWEEN '20170701 00:00:00' AND '20170731 00:00:00'
第二个查询是:
DECLARE @ReportMode VARCHAR(20),
@ApplictnDate DATETIME;
SET @ApplictnDate =
CASE
WHEN @ReportMode = 'Completions' THEN '20160801 00:00:00'
WHEN @ReportMode = 'Pipeline' THEN '20170201 00:00:00'
END
SELECT
Id, AppDate, CompDate
FROM
TbTable
WHERE
AppDate > @ApplictnDate AND
CompDate IS NULL
问题:
我可以使用变量在
SELECT
语句中创建CASE
语句,还是需要根据@ApplictnDate
SET
它?如何以语法创建
CASE
语句来处理 NULL 或日期范围?
谢谢
如果您最近没有阅读或重读 Sommaskogs 博客文章,那么为了避免最典型的性能问题,它肯定值得一读。
我建议不要使用单个查询。这是可能的,但查询处理器将缓存它遇到的第一个版本,但对于每个 null 和非 null 值可能会有更好的计划。您可能会因此遇到性能问题。
更好的方法是对每种情况分别进行查询或程序。如果您(非常正确地(试图避免重复,请将谓词和无参数查询作为视图,然后使用不同的WHERE
子句和参数应用来分隔过程/查询。
CompDate 不需要 CASE,您可以使用 OR。
但请注意,AND 是在 OR 之前计算的。
F.e.a=1 OR b=1 AND c=1
的评估为a=1 OR (b=1 AND c=1)
,而不是(a=1 OR b=1) AND c=1
因此,请包括括号以避免 AND/OR 陷阱。
DECLARE @ApplictnDate DATETIME =
CASE @ReportMode
WHEN 'Completions' THEN '2016-08-01'
WHEN 'Pipeline' THEN '2017-02-01'
END;
DECLARE @CompDateStart DATETIME = '2017-07-01';
DECLARE @CompDateEnd DATETIME = EOMONTH(@CompDateStart);
SELECT Id,
AppDate,
CompDate
FROM TbTable
WHERE AppDate > @ApplictnDate
AND (CompDate IS NULL OR CompDate BETWEEN @CompDateStart AND @CompDateEnd);