2017-11-01 10 views
1

は今、私は毎月集計QUERY - 毎月のための一人あたりの3ヶ月平均

すべての人のための最後の3ヶ月間、この平均を取得する必要があり、私はBigQueryの

Person | Amount | yearMonth 
--------------------------- 
AA  | 100 | 201701 
AA  | 200 | 201702 
AA  | 300 | 201703 
AA  | 70 | 201704 
AB  | 10 | 201701 
AB  | 50 | 201702 
AB  | 60 | 201703 
AB  | 70 | 201704 
AC  | 70 | 201701 
AC  | 80 | 201702 
AC  | 30 | 201703 
AC  | 10 | 201704 

にデータのビューを持っていると仮定します

期待される結果:これはどのように計算され

Person | Amount | yearMonth 
--------------------------- 
AA  | 200 | 201703(avg of 201701-201703) 
AA  | 190 | 201704(avg of 201702-201704) 
AB  | 40 | 201703(avg of 201701-201703) 
AB  | 60 | 201704(avg of 201702-201704) 
AC  | 60 | 201703(avg of 201701-201703) 
AC  | 40 | 201704(avg of 201702-201704) 

最初の行

  • AA = 200は、+ 100(201701)+200(201702)+300(201703)/ 3 = 200
  • AA = 100から200(201702)から来る来ます300(201703)+70(201704)/ 3 = 190
  • AB = 40、10(201701)+50(201702)60(201703)/ 3 = 40
  • とすぐ
から来ます

私はこれでどのようにグループ化するのか分かりません。あなたの答えがこの問題へのリンクを持っているのであれば、私は気にしません。

ありがとうヒープ

レガシーSQLでも可能ですか?私はまだstandardSQLに移行していません。 私の見解は、従来のSQLである以下

+1

で例の下に使用してそれで遊ぶあなたも、あなたのビューを移行支援が必要な場合は、別の質問を投稿考えてみましょう標準のSQLに変換します。 –

答えて

2

#standardSQL 
SELECT 
    person, yearMonth, CAST(amount AS INT64) amount 
FROM (
    SELECT 
    person, yearMonth, dt, 
    AVG(amount) OVER(PARTITION BY person ORDER BY dt RANGE BETWEEN 63 PRECEDING AND CURRENT row) amount, 
    COUNT(1) OVER(PARTITION BY person ORDER BY dt RANGE BETWEEN 63 PRECEDING AND CURRENT row) months 
    FROM (
    SELECT 
     person, amount, yearMonth, 
     UNIX_DATE(DATE(DIV(yearMonth, 100), MOD(yearMonth, 100), 1)) AS dt 
    FROM `project.dataset.table` 
) 
) 
WHERE months = 3 
-- ORDER BY person, yearMonth 

あなたが/テストダミーでそれで遊ぶことができます(少なくとも適切なグループ化のロジックにあなたのアイデアを与える必要があります)BigQueryの標準SQLのためであります

#standardSQL 
WITH `project.dataset.table` AS (
    SELECT 'AA' person, 100 amount, 201701 yearMonth UNION ALL 
    SELECT 'AA', 200, 201702 UNION ALL 
    SELECT 'AA', 300, 201703 UNION ALL 
    SELECT 'AA', 70, 201704 UNION ALL 
    SELECT 'AB', 10, 201701 UNION ALL 
    SELECT 'AB', 50, 201702 UNION ALL 
    SELECT 'AB', 60, 201703 UNION ALL 
    SELECT 'AB', 70, 201704 UNION ALL 
    SELECT 'AC', 70, 201701 UNION ALL 
    SELECT 'AC', 80, 201702 UNION ALL 
    SELECT 'AC', 30, 201703 UNION ALL 
    SELECT 'AC', 10, 201704 
) 
SELECT 
    person, yearMonth, CAST(amount AS INT64) amount 
FROM (
    SELECT 
    person, yearMonth, dt, 
    AVG(amount) OVER(PARTITION BY person ORDER BY dt RANGE BETWEEN 63 PRECEDING AND CURRENT row) amount, 
    COUNT(1) OVER(PARTITION BY person ORDER BY dt RANGE BETWEEN 63 PRECEDING AND CURRENT row) months 
    FROM (
    SELECT 
     person, amount, yearMonth, 
     UNIX_DATE(DATE(DIV(yearMonth, 100), MOD(yearMonth, 100), 1)) AS dt 
    FROM `project.dataset.table` 
) 
) 
WHERE months = 3 
ORDER BY person, yearMonth 

以下の期待通りの出力が

person yearMonth amount 
AA  201703  200 
AA  201704  190 
AB  201703  40 
AB  201704  60 
AC  201703  60 
AC  201704  40  
0であるとしてデータ
BigQueryのレガシーSQL

#legacySQL 
SELECT 
    person, yearMonth, INTEGER(amount) amount 
FROM (
    SELECT 
    person, yearMonth, dt, 
    AVG(amount) OVER(PARTITION BY person ORDER BY dt range BETWEEN 63*60*60*24 preceding AND current row) amount, 
    COUNT(1) OVER(PARTITION BY person ORDER BY dt range BETWEEN 63*60*60*24 preceding AND current row) months 
    FROM (
    SELECT 
     person, amount, yearMonth, 
     TIMESTAMP_TO_SEC(TIMESTAMP(CONCAT(STRING(INTEGER(yearMonth/100)), '-', SUBSTR(STRING(100 + yearMonth % 100), 2, 2), '-01'))) AS dt 
    FROM [project:dataset.table] 
) 
) 
WHERE months = 3 
-- ORDER BY person, yearMonth 

ため

追加バージョンあなたがテストすることができます/ダミーデータ

#legacySQL 
SELECT 
    person, yearMonth, INTEGER(amount) amount 
FROM (
    SELECT 
    person, yearMonth, dt, 
    AVG(amount) OVER(PARTITION BY person ORDER BY dt range BETWEEN 63*60*60*24 preceding AND current row) amount, 
    COUNT(1) OVER(PARTITION BY person ORDER BY dt range BETWEEN 63*60*60*24 preceding AND current row) months 
    FROM (
    SELECT 
     person, amount, yearMonth, 
     TIMESTAMP_TO_SEC(TIMESTAMP(CONCAT(STRING(INTEGER(yearMonth/100)), '-', SUBSTR(STRING(100 + yearMonth % 100), 2, 2), '-01'))) AS dt 
    FROM -- [project:dataset.table] 
     (SELECT 'AA' person, 100 amount, 201701 yearMonth), 
     (SELECT 'AA' person, 200 amount, 201702 yearMonth), 
     (SELECT 'AA' person, 300 amount, 201703 yearMonth), 
     (SELECT 'AA' person, 70 amount, 201704 yearMonth), 
     (SELECT 'AB' person, 10 amount, 201701 yearMonth), 
     (SELECT 'AB' person, 50 amount, 201702 yearMonth), 
     (SELECT 'AB' person, 60 amount, 201703 yearMonth), 
     (SELECT 'AB' person, 70 amount, 201704 yearMonth), 
     (SELECT 'AC' person, 70 amount, 201701 yearMonth), 
     (SELECT 'AC' person, 80 amount, 201702 yearMonth), 
     (SELECT 'AC' person, 30 amount, 201703 yearMonth), 
     (SELECT 'AC' person, 10 amount, 201704 yearMonth) 
) 
) 
WHERE months = 3 
ORDER BY person, yearMonth 
+0

あなたの努力に感謝します。標準SQLを提供してくれてありがとう。これは私をはっきりさせます。 – hnandarusdy

+0

あなたが私に尋ねるのが気にならないなら、 "63 * 60 * 60 * 24"とは何ですか?私は60 * 60 * 24 = 1日のタイムスタンプを仮定しますが、63が何であるかはわかりません。とにかく、今月を除外する必要があるという要件の変更があります。たとえば、201704は201701から201703の平均を意味するので、それを理解して変更する方法を探しています。範囲として63日を使用する – hnandarusdy

+0

は、過去3ヶ月間の平均を数えていることを確認します。この番号は62から約80 + 0になる可能性があります –

関連する問題