2017-08-09 70 views
0

我正在嘗試合併一對幾乎相同的查詢,它們根據參數化變量(管道和完成)使用略有不同的WHERE子句。SQL Server:WHERE子句中的DATE或NULL變量

我很努力地找出最佳的方式來編碼查找日期範圍或NULL,具體取決於@ReportMode變量。

在一審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 

問題

  1. 我能創造一個CASE聲明無線使用變量細化SELECT聲明或將它按@ApplictnDate需要爲SET

  2. 如何在語法上創建CASE語句來處理NULL或日期範圍?

感謝

+1

只需使用OR和()來將where語句保留爲一個單元? – Steve

+0

只是爲了挑剔:'CASE'是T-SQL中的一個**表達式**(比如'a + b') - 不是一個聲明。它被評估爲單一的原子價值。 –

回答

2

如果你還沒有讀過或重新讀Sommaskogs blog post最近,它肯定是值得一讀,以避免最典型的性能問題。

0

CompDate不需要CASE,您可以使用OR。

但請注意,在OR之前評估AND。
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); 
0

我建議對單個查詢。這是可能的,但查詢處理器會緩存它遇到的第一個版本,但是對於每個null和非null值可能會有更好的計劃。可能你會因此而遇到性能問題。

更好的方法是針對每種情況的單獨查詢或過程。如果您(非常正確地)試圖避免重複,則將謂詞和無參數查詢作爲視圖,然後使用不同的WHERE子句和參數應用來分隔程序/查詢。