sql >> データベース >  >> RDS >> Sqlserver

CTEを使用してSQLServerクエリ出力の欠落日を入力する

    先週、私の同僚の1人が、クエリ出力に欠落している日付を入力するためのクエリの作成を手伝ってくれるように私に依頼しました。私はいくつかの解決策に出くわしましたが、どちらも私には便利ではないようでした。そこで、再帰CTEまたは共通テーブル式を使用して独自にコンパイルしました。

    問題の説明

    2021年6月1日から10日までのカスタマーケアの着信レコードを含むテーブルがあるとします。一部の日には、コールレコードがありません。 datetime列でGROUPBYステートメントを実行すると、一部の日が欠落します。必要な出力は、欠落している日付は0の値になります。サンプル出力は以下のようになります:

    クエリ

    SELECT CONVERT(varchar(10),B.call_time,111) AS OriginalDate, COUNT(*) as total
    FROM Test1 B
    GROUP BY CONVERT(varchar(10),B.call_time,111)
    ORDER BY CONVERT(varchar(10),B.call_time,111)

    サンプル出力

    必要な出力

    ソリューションへの私のアプローチ

    単純なGROUPBYクエリを使用するのではなく、CTEとSUBQUERYが使用されます。再帰CTEは日付範囲を生成するために使用され、LEFTOUTERJOINは値と日付を組み合わせるために使用されます。ステップバイステップで説明しましょう。

    CTE/共通テーブル式

    CTEまたは共通テーブル式は、単純なクエリから派生し、単一のSELECT / INSERT / UPDATE / DELETE / MERGE /CREATEVIEWステートメントの実行スコープ内で定義される一時的な名前付き結果セットを指定します。再帰CTEとも呼ばれるそれ自体を参照することもできます。

    データの準備

    -- Create the table
    CREATE TABLE Test1(
    call_time datetime,
    name    varchar(10) default ('Mehedi')
    )
    GO
    -- Populate with sample data
    INSERT INTO Test1 (call_time, name)
    VALUES ('2021-06-01 08:00','A')
    ,('2021-06-01 09:05','C')
    ,('2021-06-01 12:50','E')
    ,('2021-06-01 16:17','D')
    ,('2021-06-01 18:53','G')
    ,('2021-06-03 11:07','F')
    ,('2021-06-03 13:09','A')
    ,('2021-06-03 16:26','E')
    ,('2021-06-03 19:56','C')
    ,('2021-06-03 21:24','A')
    ,('2021-06-04 19:13','A')
    ,('2021-06-04 11:45','B')
    ,('2021-06-04 15:02','C')
    ,('2021-06-08 23:02','A')
    ,('2021-06-09 03:04','E')

    クエリを作成する

    まず、日付範囲内のすべての日付を生成するCTEを作成します。

    DECLARE @StartDate DATE, @EndDate DATE
    SET @StartDate = '2021-11-01'
    SET @EndDate = '2021-11-08'
    ;WITH cte AS
    (    SELECT @StartDate AS sDate
    UNION ALL
    SELECT DATEADD(DAY,1,sDate)
    FROM cte
    WHERE sDate < @EndDate
    )
    SELECT  sDate
    FROM cte;

    これで、このCTEがリファクタリングされ、LEFT OUTER JOINを使用してサブクエリが作成され、値を持たない日付が表示され、値が0になります。

    DECLARE @startdate DATETIME = '2021-06-01'
    DECLARE @endDate DATETIME = '2021-06-10'
    ;WITH cte
    AS
    (
    SELECT @startdate as sDate
    UNION All
    SELECT DATEADD(day,1,sDate) From cte where DATEADD(day,1,sDate) <= @endDate
    )
    SELECT
    C.OriginalDate
    ,C.total
    FROM
    (
    SELECT CONVERT(varchar(10),A.sDate,111) AS OriginalDate, COUNT(B.call_time) as total
    FROM cte A
    LEFT OUTER JOIN Test1 B
    ON A.sDate = CONVERT(varchar(10),B.call_time,111)
    GROUP by CONVERT(varchar(10),A.sDate,111)
    ) C
    ORDER BY C.OriginalDate

    最終出力

    結論

    うまくいけば、それはあなたのために役立つでしょう。ハッピーTSQLing!

    私の個人ブログでも利用できます!


    1. ruby-oci8をインストールするにはどうすればいいですか?

    2. Python FlaskとMySQLを使用してゼロからWebアプリを作成する:パート3

    3. FORのSQLクエリ動的テーブル名

    4. テキストを含むSQLServerIDENTITY列