2

私は PostgreSQL 9.4 に SQL クエリを持っていますが、データをプルしているテーブルのためにより複雑ですが、要約すると次のようになります。

SELECT entry_date, user_id, <other_stuff>
FROM <tables, joins, etc>
GROUP BY entry_date, user_id
WHERE <whatever limits I want, such as limiting the date range or users>

その結果、ユーザーごとに、データがある日ごとに 1 つの行があります。一般に、このクエリは 1 か月の entry_date 期間に対して実行され、ユーザーごとにその月の 1 日あたり 1 つの行を持つという望ましい結果が得られます。

問題は、すべてのユーザーのデータが毎日あるとは限らず、このクエリはデータのある日の行のみを返すことです。

一部の行にデータ (日付とユーザー以外) がない場合でも、ユーザーごとに 1 日 1 行を返すように、このクエリを変更する方法はありますか?

で参加しようとしましたgenerate_series()が、うまくいきませんでした。ユーザーごとではなく、欠落した日をなくすことができます。私が本当に必要としているのは、「リスト内の各ユーザーについて、一連の(user,date)レコードを生成する」のようなものです

編集: 明確にするために、私が探している最終結果は、データベース内の各ユーザー (ユーザー テーブルのレコードとして定義) について、日付ごとに 1 つの行が必要です。したがって、where 句で 5/1/15 ~ 5/31/15 の日付範囲を指定すると、ユーザーごとに 31 行が必要になります。そのユーザーがその範囲にデータを持っていなかったり、2、3 日のデータしか持っていなかったとしてもです。日々。

4

1 に答える 1

7

generate_series()は正しい考えでした。詳細を正しく理解していない可能性があります。次のように機能します。

WITH cte AS (
   SELECT entry_date, user_id, <other_stuff>
   FROM   <tables, joins, etc>
   GROUP  BY entry_date, user_id
   WHERE  <whatever limits I want>
   ) 
SELECT *
FROM  (SELECT DISTINCT user_id FROM cte) u
CROSS  JOIN (
   SELECT entry_date::date 
   FROM   generate_series(current_date - interval '1 month'
                        , current_date - interval '1 day'
                        , interval '1 day') entry_date
   ) d
LEFT   JOIN cte USING (user_id, entry_date);

「昨日」で終わる 1 か月の実行時間ウィンドウを選択しました。「月」を正確に定義していません。

entry_dateデータ型であると仮定しますdate

更新された要件に対してよりシンプルに

テーブル内のすべてのユーザーusers(現在の選択ではなく) および指定された時間範囲の結果を取得するには、より簡単になります。CTE は必要ありません。

SELECT *
FROM   (SELECT user_id FROM users) u
CROSS  JOIN (
   SELECT entry_date::date 
   FROM   generate_series(timestamp '2015-05-01'
                        , timestamp '2015-05-31'
                        , interval '1 day') entry_date
   ) d
LEFT   JOIN (
   SELECT entry_date, user_id, <other_stuff>
   FROM   <tables, joins, etc>
   GROUP  BY entry_date, user_id
   WHERE  <whatever>
   ) t USING (user_id, entry_date);

なぜこの特定の方法で を呼び出すのgenerate_series()ですか?

また、ロケール設定に関係なく機能するISO 8601 日付形式 ( YYYY-MM-DD)を使用することをお勧めします。

于 2015-06-23T21:27:15.490 に答える