BigQuery Standard Получить первое не нулевое значение при группировке - PullRequest
0 голосов
/ 29 мая 2020

У меня есть такая таблица:

CUSTOMERS_ID  DATE_SALES  DIMENSION
MARIO1        20200201    NULL
MARIO1        20200113    Spain
MARIO2        20200131    NULL
MARIO3        20200101    France
MARIO3        20191231    Spain

, и мне нужно заказать по полям CUSTOMERS_ID и DATE_SALES DES C. Затем я хочу сгруппировать по полю CUSTOMERS_ID и получить первое ненулевое значение поля DIMENSION . Выходная таблица будет:

CUSTOMERS_ID  DIMENSION
MARIO1        Spain
MARIO2        NULL
MARIO3        France

Есть идеи? Я пробовал COALESCE функций, FIRST_VALUE, но не получил ожидаемых результатов.

Заранее спасибо!

Ответы [ 3 ]

1 голос
/ 29 мая 2020

Вы можете группировать по идентификатору клиента и использовать ARRAY_AGG, игнорируя NULLS, а также можете упорядочить по дате в этом поле. Ограничение 1 сделает его более эффективным за счет использования меньшего объема оперативной памяти. А затем OFFSET (0) сделает его непроверенным полем, так что вы можете легко использовать это поле.

WITH 
raw_data AS
(
  SELECT 'MARIO1' CUSTOMERS_ID, 20200201 DATE_SALES, NULL as DIMENSION UNION ALL
  SELECT 'MARIO1' CUSTOMERS_ID, 20200113 DATE_SALES, 'Spain' as DIMENSION UNION ALL
  SELECT 'MARIO2' CUSTOMERS_ID, 20200131 DATE_SALES, NULL as DIMENSION UNION ALL
  SELECT 'MARIO3' CUSTOMERS_ID, 20200101 DATE_SALES, 'France' as DIMENSION UNION ALL
  SELECT 'MARIO3' CUSTOMERS_ID, 20191231 DATE_SALES, 'Spain' as DIMENSION
)
SELECT CUSTOMERS_ID, ARRAY_AGG(DIMENSION IGNORE NULLS ORDER BY DATE_SALES DESC LIMIT 1)[OFFSET(0)] as DIMENSION
FROM raw_data
GROUP BY 1
1 голос
/ 29 мая 2020

Ниже для BigQuery Standard SQL

#standardSQL
SELECT AS VALUE ARRAY_AGG(t ORDER BY IF(DIMENSION IS NULL, NULL, DATE_SALES) DESC LIMIT 1)[OFFSET(0)]
FROM `project.dataset.table` t
GROUP BY CUSTOMERS_ID   

если применить к образцу данных из вашего вопроса - результат будет

Row CUSTOMERS_ID    DATE_SALES  DIMENSION    
1   MARIO1          20200113    Spain    
2   MARIO2          20200131    null     
3   MARIO3          20200101    France   
0 голосов
/ 29 мая 2020

Мы можем просто использовать здесь трюк ROW_NUMBER:

WITH cte AS (
SELECT CUSTOMERS_ID,
       ROW_NUMBER() OVER (PARTITION BY CUSTOMERS_ID
                          ORDER BY -1.0*UNIX_SECONDS(DATE_SALES) DESC) rn
    FROM yourTable
)

SELECT CUSTOMERS_ID, DIMENSION
FROM cte
WHERE rn = 1
ORDER BY CUSTOMERS_ID;

Лог c должен упорядочить номер строки по убыванию по отрицательному количеству секунд с начала эпохи. Это ставит на первое место более свежие продажи, а также помещает NULL в самый конец, поэтому значение NULL будет получать строку номер 1 только в том случае, если не будут доступны данные измерения, отличные от NULL.

...