7

選択した場所の特定の範囲の間で1日あたりのレコード数をカウントするために使用される次のストアドプロシージャを作成しました。

[dbo].[getRecordsCount] 
@LOCATION as INT,
@BEGIN as datetime,
@END as datetime

SELECT
ISNULL(COUNT(*), 0) AS counted_leads, 
CONVERT(VARCHAR, DATEADD(dd, 0, DATEDIFF(dd, 0, Time_Stamp)), 3) as TIME_STAMP 
FROM HL_Logs
WHERE Time_Stamp between @BEGIN and @END and ID_Location = @LOCATION
GROUP BY DATEADD(dd, 0, DATEDIFF(dd, 0, Time_Stamp))

しかし、問題は、結果にゼロレコードがある日が表示されないことです。これは、WHEREステートメントがゼロ値を表示できないことと関係があると確信していますが、この問題を解決する方法がわかりません。 。

よろしくお願いしますニール

4

4 に答える 4

9

WHERE句ではなく、GROUPBYです。クエリは、存在する行のデータのみを返します。つまり、タイムスタンプの日付でグループ化すると、行がある日のみが返されます。SQL Serverは、コンテキストから「空白を埋める」ことを認識できず、何を使用するかを認識しません。

通常の答えは、見たい日をすべて生成するCTEであり、空白を埋めます。これは再帰SQLステートメントを必要とするため少し注意が必要ですが、よく知られている方法です。

WITH CTE_Dates AS
(
    SELECT @START AS cte_date
    UNION ALL
    SELECT DATEADD(DAY, 1, cte_date)
    FROM CTE_Dates
    WHERE DATEADD(DAY, 1, cte_date) <= @END
)
SELECT
cte_date as TIME_STAMP,
ISNULL(COUNT(HL_Logs.Time_Stamp), 0) AS counted_leads, 
FROM CTE_Dates
LEFT JOIN HL_Logs ON DATEADD(dd, 0, DATEDIFF(dd, 0, Time_Stamp)) = cte_date
WHERE Time_Stamp between @BEGIN and @END and ID_Location = @LOCATION
GROUP BY cte_date

内訳を見ると、CTEは自分自身を参照するユニオンを使用して、前の日付に一度に1日を再帰的に追加し、その日付をテーブルの一部として記憶します。CTEを使用し、そこから*を選択した単純なステートメントを実行した場合、開始から終了までの日付のリストが表示されます。次に、ステートメントは、ログのタイムスタンプの日付に基づいてこの日付のリストをログテーブルに結合しますが、左側の結合を使用してログエントリがない日付を保持します(「左側」に一致する行があるかどうかに関係なく、すべての行を「左側」から取得します。右側かどうか)。最後に、代わりに日付とカウントでグループ化し、必要な答えを取得する必要があります。

于 2012-09-11T15:11:12.403 に答える
4

カウントするデータがない場合、返す行はありません。

空の日を 0 として含める場合は、テーブル (または一時テーブル、またはサブクエリ) を作成して日を格納し、そこからクエリに結合する必要があります。

例:次のようなもの

SELECT 
    COUNT(*) AS counted_leads,  
    CONVERT(VARCHAR, DATEADD(dd, 0, DATEDIFF(dd, 0, Time_Stamp)), 3) as TIME_STAMP  
    FROM 
        TableOfDays
           left join
        HL_Logs 
           on TableOfDays.Date = convert(date,HL_Logs.Time_Stamp)
           and ID_Location = @LOCATION 
    WHERE TableOfDays.Date between @BEGIN and @END 
    GROUP BY DATEADD(dd, 0, DATEDIFF(dd, 0, Time_Stamp)) 
于 2012-09-11T15:08:32.803 に答える
0

私はつい最近似たような仕事をしており、これを仕事の背景として使用しました。ただし、robwilliams が説明したように、私も Keith のソリューションを機能させることができませんでした。私の仕事は少し異なりました。私は数時間と数日でそれを行っていましたが、ニールラッドの質問に対する解決策は次のようになると思います

DECLARE @Start as DATETIME
       ,@End as DATETIME
       ,@LOCATION AS INT;


WITH CTE_Dates AS
(
    SELECT @Start AS cte_date, 0 as 'counted_leads'
    UNION ALL
    SELECT DATEADD(DAY, 1, cte_date) as cte_date, 0 AS 'counted_leads'
    FROM CTE_Dates  
    WHERE DATEADD(DAY, 1, cte_date) <= @End
)
SELECT cte_date AS 'TIME_STAMP'
      ,COUNT(HL.ID_Location) AS 'counted_leads'
FROM CTE_Dates 
LEFT JOIN HL_Logs AS HL ON CAST(HL.Time_Stamp as date) = CAST(cte_date as date)
AND DATEPART(day, HL.Time_Stamp) = DATEPART(day,cte_date)
AND HL.ID_Location = @LOCATION
group by cte_date
OPTION (MAXRECURSION 0)
于 2016-09-27T15:10:01.700 に答える
0

左外部結合を使用します。そのような

select count(stuff_ID), extra_NAME 
from dbo.EXTRAS 
left outer join dbo.STUFF on suff_EXTRA = extra_STUFF 
group by extra_NAME 
于 2015-09-18T17:35:28.407 に答える