2013-11-26 49 views
5

Redshiftで異なるオブジェクトの累積数を時系列で取得しようとしています。単純なことは、COUNT(DISTINCT myfield)OVER(ORDER BY時間フィールドDESC ROWS UNBOUNDED PRECEDING)を使用することですが、Redshiftは「ウィンドウ定義はサポートされていません」というエラーを出します。Redshift SQLを使用して累積別個のエンティティを数えようとしています

たとえば、以下のコードでは、最初の週から現在までの週ごとの累積別ユーザーを検索しようとしています。しかし、私は、 "サポートされていないウィンドウ関数"エラーを取得します。

SELECT user_time.weeks_ago, 
     COUNT(distinct user_time.user_id) OVER 
      (ORDER BY weeks_ago desc ROWS UNBOUNDED PRECEDING) as count 
FROM (SELECT FLOOR(EXTRACT(DAY FROM sysdate - ev.time)/7) AS weeks_ago, 
       ev.user_id as user_id 
     FROM events as ev 
     WHERE ev.action='some_user_action') as user_time 

目的は、アクションを実行した一意のユーザーの累積時系列を作成することです。これを行う方法に関するアイデア?

答えて

3

答えを見つけました。このトリックはネストされたサブクエリのセットであることが分かりました。内側のサブクエリは各ユーザーの最初のアクションの時間を計算します。真ん中のサブクエリは、期間あたりの総アクションをカウントし、最終的に外側のクエリは、時系列にわたる累積和を実行します。

(SELECT engaged_per_week.week as week, 
     SUM(engaged_per_week.total) over (order by engaged_per_week.week DESC ROWS UNBOUNDED PRECEDING) as total 
FROM 
    -- COUNT OF FIRST TIME ENGAGEMENTS PER WEEK 
    (SELECT engaged.first_week AS week, 
      count(engaged.first_week) AS total 
    FROM 
     -- WEEK OF FIRST ENGAGEMENT FOR EACH USER 
     (SELECT MAX(FLOOR(EXTRACT(DAY FROM sysdate - ev.time)/7)) as first_week 
     FROM  events ev 
     WHERE ev.name='some_user_action' 
     GROUP BY ev.user_id) AS engaged 

    GROUP BY week) as engaged_per_week 
ORDER BY week DESC) as cumulative_engaged 
1

はここhereを引用例に適用する方法です、プラス私は別の行を追加しましたこれがどのようにして別々のものであるかを実証するために '2015-01-01'のために 'テーブル'を複製する。

例の著者は解決策については間違っていますが、私は彼の例を使用しています。

create table public.test 
(
    "date" date, 
    item varchar(8), 
    measure int 
) 

insert into public.test 
    values 
     ('2015-01-01', 'table', 12), 
     ('2015-01-01', 'table', 120), 
     ('2015-01-01', 'chair', 51), 
     ('2015-01-01', 'lamp', 8), 
     ('2015-01-02', 'table', 17), 
     ('2015-01-02', 'chair', 72), 
     ('2015-01-02', 'lamp', 23), 
     ('2015-01-02', 'bed',  1), 
     ('2015-01-02', 'dresser', 2), 
     ('2015-01-03', 'bed',  1); 

WITH x AS (
    SELECT 
     *, 
     DENSE_RANK() 
     OVER (PARTITION BY date 
     ORDER BY item) AS dense_rank 
    FROM public.test 
) 
SELECT 
    "date", 
    item, 
    measure, 
    max(dense_rank) 
    OVER (PARTITION BY "date") 
FROM x 
ORDER BY 1; 

サブクエリはあなたに日付ごとに各項目のランクを取得し、その後、メインクエリは、あなたに、日付ごとにその濃密ランク、つまり、日付ごとの項目の明確な数の最大値を取得します。

高密度ランクではなく、奇数を数えるためには、ランクがである必要があります。

+0

私は動作しません同じリンクされている例を見ました。しかし、これは助けになりました。ありがとう。 – systemjack

+0

'select *'ですべての行を返すことを望まないときはどうしますか? 1ヶ月の間に別個の顧客を数えたい場合がありますが、私がパーティションの 'customer_id'で注文すると、その月の最大値だけが必要であっても、返された集合はすべてのランク値を与えます。 – Merlin

2

かわりに、カウント(明確な)のDENSE_RANKを使用する必要があります。

DENSE_RANK() OVER(PARTITION BY weeks_ago ORDER BY user_time.user_id) 
関連する問題