2017-04-01 77 views
0

假設指示間隔I有兩個表:intervals包含索引間隔(其列是i_mini_max)和values包含索引值(的列ix)。這裏有一個例子:大量查詢/ 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的值,每個間隔:

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 

不同之處在於:

 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 | 
+-------+-------+-----+ 

在一些SQL引擎,這可以用做BigQuery不允許使用查詢類型(「在SELECT子句中不允許使用子選擇」或「如果沒有條件等於來自連接兩邊的字段的條件,則不能使用」LEFT OUTER JOIN「」取決於synta x使用)。

必須有一種方法可以用窗口函數做到這一點,但我無法弄清楚 - 我看過的所有例子都將分區作爲表的一部分。有沒有不使用CROSS JOIN的選項?如果沒有,做這個CROSS JOIN最有效的方法是什麼?

我的數據的一些注意事項:

  • 這兩個表包含許多(10⁸-10⁹)行。
  • intervals中可能有重複,而不是i
  • intervals中的兩個區間要麼相同,要麼完全不相交(不重疊)。
  • 所有間隔的並集通常接近所有值的集合(所以它形成這個空間的一個分區)。
  • 間隔可能很大(例如,i_max-i_min <10⁶)。
+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

再次感謝。出於好奇,是否有可能在傳統SQL中做到這一點? – Ted

+0

由於傳統SQL中的ON子句的限制,可以執行,但不僅僅是標準SQL的一對一轉換。但可行。 –