2017-04-01 3 views
0

は、私は2つのテーブルがあると仮定:intervalsインデックス間隔を含み(その列がi_mini_maxある)とvaluesは(列ix有する)インデックス付き値を含みます。ここでは例です:BigQueryの/ SQL:二次表で示された間隔にわたる和

values:  intervals: 
+---+---+ +-------+-------+ 
| i | x | | i_min | i_max | 
+-------+ +---------------+ 
| 1 | 1 | | 1 | 4 | 
| 2 | 0 | | 6 | 6 | 
| 3 | 4 | | 6 | 6 | 
| 4 | 9 | | 6 | 6 | 
| 6 | 7 | | 7 | 9 | 
| 7 | 2 | | 12 | 17 | 
| 8 | 2 | +-------+-------+ 
| 9 | 2 | 
+---+---+ 

私は各区間について、xの値を合計する:いくつかのSQLエンジンで

 result: 
+-------+-------+-----+ 
| i_min | i_max | sum | 
+---------------------+ 
| 1 | 4 | 13 | // 1+0+4+9 
| 6 | 6 | 7 | 
| 6 | 6 | 7 | 
| 6 | 6 | 7 | 
| 7 | 9 | 6 | // 2+2+2 
| 12 | 17 | 0 | 
+-------+-------+-----+ 

、これは使用して行うことができます

ことを除いて
SELECT 
    i_min, 
    i_max, 
    (SELECT SUM(x) 
    FROM values 
    WHERE i BETWEEN intervals.i_min AND intervals.i_max) AS sum_x 
FROM 
    intervals 

BigQueryではクエリの型が許可されていません(「SELECT句ではSubselectが許可されていません」または「LEFT OUTER JOINは結合の両側からのフィールドが等しい条件なしでは使用できません) xを使用)。

ウィンドウ関数でこれを行う方法があるに違いありませんが、私はどのように理解できません - 私が見たすべての例では、テーブルの一部としてパーティションがあります。 CROSS JOINを使用しないオプションはありますか?そうでない場合、このクロスジョインを行う最も効率的な方法は何ですか?

私のデータに関する注意:

  • 両方のテーブルには、多くの(10⁸-10⁹)行が含まれています。
  • intervalsには繰り返しがあり、iにはないことがあります。
  • しかし、intervalsの2つのインターバルは、どちらも同じで、完全に重ならない(重複しない)かどちらかです。
  • すべての間隔の和集合は、通常、すべての値の集合の近くにあります(したがって、この空間のパーティションを形成します)。i
  • 間隔が大きい場合があります(たとえば、i_max-i_min < 106)。
+1

以下のようにダミーデータで/テストを再生することができ、あなたの質問を編集して、サンプルデータと望ましい結果を提供してください。また、間隔が重複していて、コンパクトで、スパースであるかどうかについても説明します。 。 。ソリューションに影響する可能性があります。 –

+0

クエリでこの種の機能を使用するには、[標準SQLを有効にする](https://cloud.google.com/bigquery/docs/reference/standard-sql/)を必ず確認してください。 [移行ガイド](https://cloud.google.com/bigquery/docs/reference/standard-sql/migrating-from-legacy-sql)も参照してください。 –

+0

@GordonLinoff良い点、しました。 – Ted

答えて

3

以下試してみてください - BigQueryの標準SQL

#standardSQL 
SELECT 
    i_min, i_max, SUM(x) AS sum_x 
FROM (
    SELECT i_min, i_max, ROW_NUMBER() OVER() AS line FROM `project.dataset.intervals` 
) AS intervals 
JOIN (SELECT i, x FROM `project.dataset.values` UNION ALL SELECT NULL, 0) AS values 
ON values.i BETWEEN intervals.i_min AND intervals.i_max OR values.i IS NULL 
GROUP BY i_min, i_max, line 
-- ORDER BY i_min 

あなたは

#standardSQL 
WITH intervals AS (
    SELECT 1 AS i_min, 4 AS i_max UNION ALL 
    SELECT 6, 6 UNION ALL 
    SELECT 6, 6 UNION ALL 
    SELECT 6, 6 UNION ALL 
    SELECT 7, 9 UNION ALL 
    SELECT 12, 17 
), 
values AS (
    SELECT 1 AS i, 1 AS x UNION ALL 
    SELECT 2, 0 UNION ALL 
    SELECT 3, 4 UNION ALL 
    SELECT 4, 9 UNION ALL 
    SELECT 6, 7 UNION ALL 
    SELECT 7, 2 UNION ALL 
    SELECT 8, 2 UNION ALL 
    SELECT 9, 2 
) 
SELECT 
    i_min, i_max, SUM(x) AS sum_x 
FROM (SELECT i_min, i_max, ROW_NUMBER() OVER() AS line FROM intervals) AS intervals 
JOIN (SELECT i, x FROM values UNION ALL SELECT NULL, 0) AS values 
ON values.i BETWEEN intervals.i_min AND intervals.i_max OR values.i IS NULL 
GROUP BY i_min, i_max, line 
-- ORDER BY i_min 
+0

もう一度ありがとうございます。好奇心のために、これをLegacy SQLで行うことは可能ですか? – Ted

+0

レガシーSQLのON句の制限のため、標準SQLから1対1の変換だけでなく、実行可能です。しかし、実行可能です。 –

関連する問題