Получить все окна длиной 3 из массива bigquery - PullRequest
0 голосов
/ 06 ноября 2018

Если бы у меня был стол вроде:

value1 | value2 | value3
-------|--------|-------
  a    |   1    |.  z
  a    |   2    |.  x
  a.   |.  3    |.  z
  a.   |.  4    |.  x
  b.   |.  1    |.  x
  b.   |.  2    |.  z
  c.   |.  1    |.  z
  c.   |.  2    |.  x
  c.   |.  3    |.  z

И я хотел получить все упорядоченные окна трех значений из этого, такие как:

(a, [(1, z), (2, x), (3, z)]), (a, [(2, z), (3, z), (4, x)]), (c, [(1, z), (2, x), (3, z)])

используя BigQuery, как бы я сделал это в агрегации по нескольким уникальным ключам value1 и гарантировал, что они упорядочены по значению 2.

Так что мой запрос будет выглядеть примерно так:

SELECT
    val1,
    ARRAY_AGG(STRUCT(value2, value3)) vals
FROM my_table

И тогда мне понадобится запрос к окну, чтобы получить все группировки из трех значений. Я предполагаю, что мог бы использовать ROW_NUMBER () или что-то еще, но я не уверен, есть ли простой способ решить эту проблему.

1 Ответ

0 голосов
/ 07 ноября 2018

Ниже для BigQuery Standrad SQL

Версия 1:

#standardSQL
SELECT
  value1, [arr[OFFSET(pos)], arr[OFFSET(pos + 1)], arr[OFFSET(pos + 2)]] arr
FROM (
  SELECT value1, ARRAY_AGG(STRUCT(value2, value3)) arr
  FROM `project.dataset.table`
  GROUP BY value1
  HAVING ARRAY_LENGTH(arr) > 2
), UNNEST(GENERATE_ARRAY(0, ARRAY_LENGTH(arr) - 3)) pos

Версия 2:

#standardSQL
SELECT
  value1, ARRAY(SELECT s FROM UNNEST(arr) s WITH OFFSET ord WHERE ord >= pos ORDER BY ord LIMIT 3) arr
FROM (
  SELECT value1, ARRAY_AGG(STRUCT(value2, value3)) arr
  FROM `project.dataset.table`
  GROUP BY value1
  HAVING ARRAY_LENGTH(arr) > 2
), UNNEST(GENERATE_ARRAY(0, ARRAY_LENGTH(arr) - 3)) pos  

Если применить обе версии к фиктивным данным из вашего вопроса, используя ниже CTE

WITH `project.dataset.table` AS (
  SELECT 'a' value1, 1 value2, 'z' value3 UNION ALL
  SELECT 'a', 2, 'x' UNION ALL
  SELECT 'a', 3, 'z' UNION ALL
  SELECT 'a', 4, 'x' UNION ALL
  SELECT 'b', 1, 'x' UNION ALL
  SELECT 'b', 2, 'z' UNION ALL
  SELECT 'c', 1, 'z' UNION ALL
  SELECT 'c', 2, 'x' UNION ALL
  SELECT 'c', 3, 'z' 
)

результат

Row value1  arr.value2  arr.value3   
1   a       1           z    
            2           x    
            3           z    
2   a       2           x    
            3           z    
            4           x    
3   c       1           z    
            2           x    
            3           z      

Очевидно, вы можете упаковать вывод любым удобным вам способом

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...