2010-02-12 54 views
0

我正在使用CTE生成一組日期。計算日期之間的行

12/02/2010 10:00:00 12/02/2010 10:59:59 
12/02/2010 11:00:00 12/02/2010 11:59:59 
12/02/2010 12:00:00 12/02/2010 12:59:59 

然後我將它加入包含大量日期的索引視圖。

我有2個選項的時間之間的計數範圍

1),我將SUM(情況)測試LOG_DATE以測試是否它是開始和結束日期之間,+ 1代表真,0代表假 - 所以如果沒有結果我總是會得到'0'

12/02/2010 10:00:00 12/02/2010 10:59:59 0 
12/02/2010 11:00:00 12/02/2010 11:59:59 1 
12/02/2010 12:00:00 12/02/2010 12:59:59 0 

2)我可以使用每個日期範圍的WHERE子句計數(*)。

12/02/2010 11:00:00 12/02/2010 11:59:59 1 

正如你所期望1)是有效的,但對性能有巨大的開銷2)可能是8000%比較有效,但無法返回返回指定日期範圍之間的空結果應該過濾器適用範圍。

有沒有辦法使用高效的WHERE子句,但保留日期範圍的行詳細'0'?

這裏是的情況下解決一些SQL:

SELECT  [LABEL], [Display Start Date], [Display End Date], 
    SUM(CASE WHEN ([LOG].line_date BETWEEN [Start Date] AND [End Date]) THEN 1 ELSE 0 END) AS [Total Calls], 
    SUM(CASE WHEN ([LOG].line_date BETWEEN [Start Date] AND [End Date]) AND ([LOG].line_result = 1) THEN 1 ELSE 0 END) AS [1 Calls], 

FROM   [DATE RANGE FUNCTION] LEFT JOIN 
         dbo.vCallLog WITH (noexpand) as [LOG] on 0 > -1 
GROUP BY [Start Date], [End Date], [Display Start Date], [Display End Date], [LABEL] 

這裏是在WHERE解決方案的一些SQL:

SELECT  [LABEL], [Display Start Date], [Display End Date], 
        COUNT(dbo.vCallLog.line_id) AS [Total Calls], 
        SUM(CASE WHEN ([LOG].line_result = 1) THEN 1 ELSE 0 END) AS [1 Calls], 
FROM   [DATE RANGE FUNCTION] LEFT JOIN 
         dbo.vCallLog WITH (noexpand) as [LOG] on 0> -1 
WHERE  ([LOG].line_date BETWEEN [Start Date] AND [End Date]) 
GROUP BY [Start Date], [End Date], [Display Start Date], [Display End Date], [LABEL] 

回答

1

如果我理解正確的話,你可以嘗試像

DECLARE @DateRanges TABLE(
     StartDate DATETIME, 
     EndDate DATETIME 
) 

INSERT INTO @DateRanges (StartDate,EndDate) SELECT '12/02/2010 10:00:00','12/02/2010 10:59:59' 
INSERT INTO @DateRanges (StartDate,EndDate) SELECT '12/02/2010 11:00:00','12/02/2010 11:59:59' 
INSERT INTO @DateRanges (StartDate,EndDate) SELECT '12/02/2010 12:00:00','12/02/2010 12:59:59' 

DECLARE @DateValues TABLE(
     DateVal DATETIME 
) 

INSERT INTO @DateValues (DateVal) SELECT '12/02/2010 11:00:00' 
INSERT INTO @DateValues (DateVal) SELECT '12/02/2010 11:01:00' 
INSERT INTO @DateValues (DateVal) SELECT '12/02/2010 12:01:00' 

SELECT t.StartDate, 
     t.EndDate, 
     COUNT(tv.DateVal) CountVal 
FROM @DateRanges t LEFT JOIN 
     @DateValues tv ON tv.DateVal BETWEEN t.StartDate AND t.EndDate 
GROUP BY t.StartDate, 
      t.EndDate 

輸出

StartDate    EndDate     CountVal 
----------------------- ----------------------- ----------- 
2010-12-02 10:00:00.000 2010-12-02 10:59:59.000 0 
2010-12-02 11:00:00.000 2010-12-02 11:59:59.000 2 
2010-12-02 12:00:00.000 2010-12-02 12:59:59.000 1 
+0

不幸的是,它仍然忽略沒有匹配行的範圍。 –

+0

您是否嘗試運行該示例,我添加了測試用例的輸出 –

+0

yes是該示例按預期工作,因此當類似的概念表(1帶有日期範圍,另一個日期列表......本質上)出現混淆時複製我一直期望的左連接。事實上,它包含我的'日期行'的索引視圖是一個因素? –

2

好,有點pokery,我意識到我犯了一個輕微的問題對我的自我:

的問題是,WHERE子句以及它與COUNT子句位置。如果我在同一結果集上使用WHERE &,那麼在日期之間我不會得到任何零行。但是,如果我計算所有內容並忽略相同結果集中的WHERE子句,並將WHERE子句放在JOIN 即[x]左連接(從[b]選擇[a],其中[x]在@x &y之間)作爲[c]我返回所有的行,然後計數litrally計數。

我認爲這個問題是在WHERE子句以前中省略計數選擇,因爲沒有要採取的行動(根據編譯)

0

啊,臭名昭著的WHERE陷阱。當你有一個LEFT JOIN和WHERE,在右欄測試一個條件,條款,你必須包括

WHERE (<Condition based on rightHandTable.Column> OR rightHandTable.Column IS NULL) 

這也是擺在括號尾隨或語句時,你有化合物,其中的條件是一個好主意:

WHERE a=1 AND b=1 OR b iS NULL 

此評估爲真時,a和b = 1,或當b爲null

,距離

WHERE a=1 AND (b=1 OR b is NULL) 
不同

這意味着必須是1並且b必須是1或者null