BigQuery: LAG () в UNNEST () - PullRequest
       5

BigQuery: LAG () в UNNEST ()

0 голосов
/ 12 октября 2018

Я рассматривал использование LAG() для возврата значения из предыдущей строки в ARRAY of STRUCT, и похоже, что функции окна навигации, такие как LAG/LEAD, не поддерживаются с UNNEST.

Это звучит неоптимально, но вам нужно UNNEST все и (ре) PARTITION BY !!

Например, вы хотите указать сумму предыдущей строки:

РЕДАКТИРОВАТЬ : Подробности схемы:

Схема счетов: docID STRING, lines STRUCT<lineID STRING, amount NUMERIC>

Ожидаемый результат: docID STRING, lines STRUCT<lineID STRING, amount NUMERIC, prev_amount NUMERIC>

SELECT 
   docID, lineID, amount
   ,LAG(amount) OVER (PARTITION BY docID ORDER by lineID) prev_amount
FROM invoices, UNNEST(lines)

Thisдовольно медленноЯ хотел бы, чтобы мы могли как-то передать массив как оконную раму для использования.

Любая альтернатива? Я использую BigQuery, но это может относиться к другим СУБД.

ОБНОВЛЕНИЕ : Я пришелс альтернативой ниже, используя WITH OFFSET.Быстрее, и, возможно, это то, для чего предназначен OFFSET, он просто уродлив и может показаться мне более простым.

SELECT 
   docID, lineID, amount
   ,(SELECT amount FROM UNNEST(lines) WITH OFFSET AS pos2 WHERE pos2 = pos - 1) prev_amount
FROM invoices, UNNEST(lines) WITH OFFSET AS pos

Ответы [ 2 ]

0 голосов
/ 13 октября 2018

Ниже альтернативы ответу Михаила, используя вместо этого WITH OFFSET, он работает лучше (55 с против 170 с, более 50 миллионов строк)

#standardSQL
SELECT docID, ARRAY(
    SELECT AS STRUCT 
      l.*, 
      lines[SAFE_OFFSET(pos - 1)].amount prev_amount 
    FROM UNNEST(lines) l WITH OFFSET pos
    ) lines
FROM invoices

Примечание: это не будет работать как есть, если ORDER BY илив * unesting добавлено предложение WHERE, которое изменяет исходную индексацию.

Это был мой вариант использования, и если вы после относительного позиционирования в отфильтрованном массиве , вы должны использоватьподзапрос, чтобы сначала создать отфильтрованный массив, а затем комбинацию UNNEST WITH OFFSET + OFFSET/ORDINAL во внешнем запросе.

0 голосов
/ 12 октября 2018

Ниже показана лучшая производительность (по крайней мере, на небольшом количестве, с которым я запускаю его для быстрого тестирования).Кроме того, план выполнения выглядит намного лучше (по крайней мере для меня)

#standardSQL
SELECT 
   lines[OFFSET(pos)].*, lines[SAFE_OFFSET(pos - 1)].amount prev_amount
FROM invoices, UNNEST(GENERATE_ARRAY(0, ARRAY_LENGTH(lines) - 1)) pos

Примечание: я предполагал следующую схему [STRUCT<docID INT64, lineID INT64, amount FLOAT64>] lines

ОБНОВЛЕНИЕ: корректировка в соответствии с реальной схемой, которую вы только чтопри условии

#standardSQL
SELECT docID, ARRAY(
    SELECT AS STRUCT 
      lines[OFFSET(pos)].*, 
      lines[SAFE_OFFSET(pos - 1)].amount prev_amount 
    FROM UNNEST(GENERATE_ARRAY(0, ARRAY_LENGTH(lines) - 1)) pos
    ) lines
FROM invoices
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...