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

ローリング日付範囲内の個別の値の数を照会します

    テストケース:

    CREATE TABLE tbl (date date, email text);
    INSERT INTO tbl VALUES
      ('2012-01-01', '[email protected]')
    , ('2012-01-01', '[email protected]')
    , ('2012-01-01', '[email protected]')
    , ('2012-01-02', '[email protected]')
    , ('2012-01-02', '[email protected]')
    , ('2012-01-03', '[email protected]')
    , ('2012-01-04', '[email protected]')
    , ('2012-01-05', '[email protected]')
    , ('2012-01-05', '[email protected]')
    , ('2012-01-06', '[email protected]')
    , ('2012-01-06', '[email protected]')
    , ('2012-01-06', '[email protected]`')
    ;
    

    クエリ-エントリがtblに存在する日のみを返します :

    SELECT date
         ,(SELECT count(DISTINCT email)
           FROM   tbl
           WHERE  date BETWEEN t.date - 2 AND t.date -- period of 3 days
          ) AS dist_emails
    FROM   tbl t
    WHERE  date BETWEEN '2012-01-01' AND '2012-01-06'  
    GROUP  BY 1
    ORDER  BY 1;
    

    または-すべての日を返します その日の行がない場合でも、指定された範囲内:

    SELECT date
         ,(SELECT count(DISTINCT email)
           FROM   tbl
           WHERE  date BETWEEN g.date - 2 AND g.date
          ) AS dist_emails
    FROM  (SELECT generate_series(timestamp '2012-01-01'
                                , timestamp '2012-01-06'
                                , interval  '1 day')::date) AS g(date);
    

    db<>ここでフィドル

    結果:

    day        | dist_emails
    -----------+------------
    2012-01-01 | 3
    2012-01-02 | 3
    2012-01-03 | 3
    2012-01-04 | 3
    2012-01-05 | 1
    2012-01-06 | 2
    

    この 最初はウィンドウ関数の仕事のようでしたが、適切なウィンドウフレームを定義する方法が見つかりませんでした。また、ドキュメントごとに:

    集計ウィンドウ関数は、通常の集計関数とは異なり、DISTINCTを許可しません またはORDER BY 関数の引数リスト内で使用されます。

    そこで、代わりに相関サブクエリを使用して解決しました。それが最も賢い方法だと思います。

    ところで、「上記の日付から3日前まで」は、 4の期間になります。 日々。あなたの定義はそこで矛盾しています。

    少し短いですが、数日間は遅くなります:

    SELECT g.date, count(DISTINCT email) AS dist_emails
    FROM  (SELECT generate_series(timestamp '2012-01-01'
                                , timestamp '2012-01-06'
                                , interval  '1 day')::date) AS g(date)
    LEFT   JOIN tbl t ON t.date BETWEEN g.date - 2 AND g.date
    GROUP  BY 1
    ORDER  BY 1;
    

    関連:

    • PostgreSQLで2つの日付間の時系列を生成する
    • 時間間隔のある行のローリングカウント


    1. 選択クエリを作成するための10のMicrosoftAccessのヒント

    2. PL / SQLを使用してファイルがイメージであるかどうかを確認するにはどうすればよいですか?

    3. SQL Server FOR JSON PATHの例(T-SQL)

    4. WebサイトのダウンとTwitterフィード