BigQuery - получите агрегированные результаты для каждой группы, даже если для некоторых из них нет участников - PullRequest
1 голос
/ 19 марта 2020

Используя BigQuery, я хочу сгруппировать страницы в зависимости от их заголовка с помощью одного запроса и рассчитать различные показатели по группам. Поскольку правила для названий не являются взаимоисключающими, я сделал это следующим образом:

SELECT SUM(views) views, ..., title_group
FROM `fh-bigquery.wikipedia_v3.pageviews_2019`, 
      UNNEST([
                CASE WHEN (title LIKE '%game%') 
                THEN 'games_group' END, 
                CASE WHEN (title LIKE '%sport%') 
                THEN 'sports_group' END, 
                CASE WHEN (title LIKE '%rarerare%')
                THEN 'rare_group' END
             ]) AS title_group
WHERE DATE(datehour) BETWEEN '2019-01-01' AND '2019-01-10'AND wiki='en'
GROUP BY title_group

И я получаю:

views       ...   title_group
3414469869  ... 
4355264     ...   games_group
1361074     ...   sports_group

То, что я хотел бы получить, немного отличается :

views     ...   title_group
4355264   ...   games_group
1361074   ...   sports_group
0         ...   rare_group

Действительно, мне нужны результаты, даже если группа не появлялась.

Как я могу изменить свой запрос, чтобы получить этот результат?

Ответы [ 2 ]

1 голос
/ 19 марта 2020

Почему бы просто не помещать значения в отдельные столбцы для каждого часа?

SELECT SUM(CASE WHEN title LIKE '%game%' THEN views ELSE 0 END) as game_views,
       SUM(CASE WHEN title LIKE '%sport%' THEN views ELSE 0 END) as sport_views,
       SUM(CASE WHEN title LIKE '%rarerare%' THEN views ELSE 0 END) as rare_views
FROM `fh-bigquery.wikipedia_v3.pageviews_2019`
WHERE DATE(datehour) BETWEEN '2019-01-01' AND '2019-01-10' AND
      wiki = 'en';

Затем вы можете отменить это, если хотите:

SELECT el.title_group, el.views
FROM (SELECT SUM(CASE WHEN title LIKE '%game%' THEN views ELSE 0 END) as game_views,
             SUM(CASE WHEN title LIKE '%sport%' THEN views ELSE 0 END) as sport_views,
             SUM(CASE WHEN title LIKE '%rarerare%' THEN views ELSE 0 END) as rare_views
      FROM `fh-bigquery.wikipedia_v3.pageviews_2019`
      WHERE DATE(datehour) BETWEEN '2019-01-01' AND '2019-01-10' AND
            wiki = 'en'
     ) v CROSS JOIN
     UNNEST([STRUCT('games_groups' as title_group, v.game_views as views),
             STRUCT('sports_groups' as title_group, v.sports_views as views),
             STRUCT('rare_groups' as title_group, v.rare_views as views)
            ]
           ) el
1 голос
/ 19 марта 2020

Самый простой способ - обернуть исходный (без каких-либо изменений) запрос дополнительным левым соединением, как в примере ниже

#standardSQL
SELECT IFNULL(views, 0) views, title_group
FROM (SELECT title_group FROM UNNEST(['games_group', 'sports_group', 'rare_group']) AS title_group)
LEFT JOIN (
  SELECT SUM(views) views, title_group
  FROM `fh-bigquery.wikipedia_v3.pageviews_2019`
  CROSS JOIN UNNEST([
    CASE WHEN (title LIKE '%game%') THEN 'games_group' END, 
    CASE WHEN (title LIKE '%sport%') THEN 'sports_group' END, 
    CASE WHEN (title LIKE '%rarerare%') THEN 'rare_group' END
  ]) AS title_group
  WHERE DATE(datehour) BETWEEN '2019-01-01' AND '2019-01-10'AND wiki='en'
  GROUP BY title_group
)
USING(title_group)
-- ORDER BY views DESC   

с выводом

Row views   title_group  
1   4355264 games_group  
2   1361074 sports_group     
3   0       rare_group    

Если вы готовы выше оптимизированный / рефакторинг - рассмотрите ниже версию (с тем же выводом очевидно)

#standardSQL
WITH title_groups AS (
  SELECT title_group, pattern 
  FROM UNNEST([STRUCT<title_group STRING, pattern STRING>
    ('games_group', '%game%'), ('sports_group', '%sport%'), ('rare_group', '%rarerare%')
  ])
)
SELECT IFNULL(views, 0) views, title_group FROM title_groups
LEFT JOIN (
  SELECT SUM(CASE WHEN title LIKE pattern THEN views END) views, title_group 
  FROM `fh-bigquery.wikipedia_v3.pageviews_2019`
  CROSS JOIN title_groups
  WHERE DATE(datehour) BETWEEN '2019-01-01' AND '2019-01-10'AND wiki='en'
  GROUP BY title_group
)
USING(title_group)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...