2016-07-14 2 views
1

ユーザーテーブルからデータを取得し、ユーザー作成時の実行中の合計と累積合計を生成するSQLクエリを作成しました。データは週ごとにグループ化されます(ポストグルのウィンドウ機能を使用)。私は左の外部結合を使用して、ユーザーが作成されていない場所がない週も含めます。ここにクエリがあります...データグラムと外部ジョインが欠けているPostgreSQLの実行合計

<!-- language: lang-sql --> 

WITH reporting_period AS (
    SELECT generate_series(date_trunc('week', date '2015-04-02'), date_trunc('week', date '2015-10-02'), interval '1 week') AS interval 
) 

SELECT 
    date(interval) AS interval 
, count(users.created_at) as interval_count 
, sum(count(users.created_at)) OVER (order by date_trunc('week', users.created_at)) AS cumulative_count 

FROM reporting_period 
LEFT JOIN users 
ON interval=date(date_trunc('week', users.created_at)) 

GROUP BY interval, date_trunc('week', users.created_at) ORDER BY interval 

これはほぼ完全に動作します。累積値は、ユーザーが作成された週に適切に計算されます。ユーザーが作成されていない数週間は、その時点までの総計ではなく、総計に設定されます。

** The Week Tot列(interval_count)の行は、期待どおり0であるが、Run Tot(cumulative_total)は1053であり、これは総計と等しいことに注意してください。

Week   Week Tot Run Tot 
----------------------------------- 
2015-03-30  | 4  | 4 
2015-04-06  | 13  | 17 
2015-04-13  | 0  | 1053 ** 
2015-04-20  | 9  | 26 
2015-04-27  | 3  | 29 
2015-05-04  | 0  | 1053 ** 
2015-05-11  | 0  | 1053 ** 
2015-05-18  | 1  | 30 
2015-05-25  | 0  | 1053 ** 
... 
2015-06-08  | 996  | 1031 
... 
2015-09-07  | 2  | 1052 
2015-09-14  | 0  | 1053 ** 
2015-09-21  | 1  | 1053 ** 
2015-09-28  | 0  | 1053 ** 

これは、外が何とか最後の列に総計を適用することができます参加する場合、トータルランニング電流を印加することが可能であることを私には思える私は

Week    Week Tot Run Tot 
----------------------------------- 
2015-03-30  | 4  | 4 
2015-04-06  | 13  | 17 
2015-04-13  | 0  | 17 ** 
2015-04-20  | 9  | 26 
2015-04-27  | 3  | 29 
2015-05-04  | 0  | 29 ** 
... 

をご希望ですが、私はそれをやる方法を失っている。

これは可能ですか?

答えて

2

これは、私がacutalテーブルでテストしたものではないので、すぐに動作するとは限りませんが、ここで重要な点はcreated_atのユーザを一定の範囲の日付に参加させることです。

with reportingperiod as (
    select intervaldate as interval_begin, 
     intervaldate + interval '1 month' as interval_end 
    from (
     SELECT GENERATE_SERIES(DATE(DATE_TRUNC('day', DATE '2015-03-15')), 
     DATE(DATE_TRUNC('day', DATE '2015-10-15')), interval '1 month') AS intervaldate 
    ) as rp 
) 

select interval_end, 
    interval_count, 
    sum(interval_count) over (order by interval_end) as running_sum 
from (
    select interval_end, 
     count(u.created_at) as interval_count 
    from reportingperiod rp 
    left join ( 
     select created_at 
     from users 
     where created_at < '2015-10-02' 
    ) u on u.created_at > rp.interval_begin 
     and u.created_at <= rp.interval_end 
    group by interval_end 
) q 
+0

これはトリックを行ったようです。あなたのお手伝いをありがとう。 – hraynaud

0

私はそれを理解しました。トリックはサブクエリでした。ここに私のアプローチは

  1. だgenerate_seriesとの結果連合
  2. データのユーザーから0
  3. 選択間隔と回数(users.created_at)のデフォルト値を呼び出すgenerate_seriesにカウント列を追加します。間隔を取得するサブクエリで結果を使用して、ステップ#2 (この時点で、結果は各間隔の重複を持つことになります)
  4. で選択すると最大取得する前に重複
  5. 使用して、ウィンドウの凝集を解消(interval_count)走っているt otal
SELECT 
interval 
, interval_count 
, SUM(interval_count) OVER (ORDER BY interval) AS cumulative_count 

FROM 
(
    SELECT interval, MAX(interval_count) AS interval_count FROM 
    (
    SELECT GENERATE_SERIES(DATE(DATE_TRUNC('week', DATE '2015-04-02')), 
    DATE(DATE_TRUNC('week', DATE '2015-10-02')), interval '1 week') AS interval, 
    0 AS interval_count 

    UNION 

    SELECT DATE_TRUNC('week', users.created_at) AS INTERVAL, 
    COUNT(users.created_at) AS interval_count FROM users 

    WHERE users.created_at < date '2015-10-02' 
    GROUP BY 1 ORDER BY 1 
) sub1 

GROUP BY interval 
) grouped_data 

私は、このアプローチで深刻なパフォーマンスの問題があるかどうかわからないが、動作するようです。誰かがより良い、よりエレガントな、またはパフォーマンスの良いアプローチをしているなら、私はフィードバックを愛するでしょう。

編集:私のソリューションが動作しない任意の時間窓によってグループにしようと
はただ、次のようで、このソリューションは、例えば

/* generate series using DATE_TRUNC('day'...)*/ 

SELECT GENERATE_SERIES(DATE(DATE_TRUNC('day', DATE '2015-04-02')), 
    DATE(DATE_TRUNC('day', DATE '2015-10-02')), interval '1 month') AS interval, 
    0 AS interval_count 

/* And this part */ 
SELECT DATE_TRUNC('day', users.created_at) AS INTERVAL, 
    COUNT(users.created_at) AS interval_count FROM users 

    WHERE users.created_at < date '2015-10-02' 
    GROUP BY 1 ORDER BY 1 

を変更しようとしたあるこれらの同様の結果を生成することが可能であるが、 4/14/15、
4/15/15 - - 5/14/15、
5/15/15 - 6/14/15
よう3/15/15のような間隔でグループ化されたデータを持っています

関連する問題