1

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) log_date を SUM(case) テストして、開始日と終了日の間にあるかどうかをテストします。+ 1 は true、0 は false - したがって、結果がない場合は常に '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% 効率的ですが、指定された日付範囲の間に null の結果を返すフィルターが適用されている場合、範囲を返すことができません。

効率的な 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]
4

3 に答える 3

2

わかりました、少し突っ込んで、私は自分自身にわずかな問題を起こしたことに気付きました:

問題は WHERE 句と COUNT 句に対するその位置です。同じ結果セットで WHERE & count を使用している場合、日付間の行がゼロの場合は何も得られません。ただし、IF では、すべてをカウントし、同じ結果セットから WHERE を省略し、WHERE 句を JOIN に配置します。つまり、[x] 左結合 ([a] を [b] から選択し、[a] は @x と @y の間) にします。 as [c]私はすべての行を返し、数えてから文字通り数えます。

問題は、(コンパイラによると)実行するアクションがなかったため、カウント選択を省略したWHERE句であったと思います

于 2010-02-12T14:26:20.237 に答える
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
于 2010-02-12T13:41:48.450 に答える
0

ああ、悪名高いWHEREの落とし穴。LEFT JOINと右側の列の条件をテストするWHERE句がある場合は、次のように含める必要があります。

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

条件が複合的な場合は、末尾のORステートメントを括弧に入れることもお勧めします。

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

これは、aおよびb = 1の場合、またはbがnullの場合にtrueと評価されます。

とは異なります

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

これは、aが1で、bが1またはnullである必要があることを意味します

于 2011-05-05T06:24:18.183 に答える