Выполнение кросс-поворота в Google BigQuery

Я задавал предыдущий вопрос о выполнении многоуровневого агрегирующего запроса по оси X здесь: Получите коды лучших патентных стран в общедоступном наборе данных BQ.

Вот как работает запрос (скопированный из принятого ответа):

Первые 2 страны по количеству и в этих странах 2 лучших кода по количеству

WITH A AS (
  SELECT country_code
  FROM `patents-public-data.patents.publications`
  GROUP BY country_code
  ORDER BY COUNT(1) DESC
  LIMIT 2
), B AS (
  SELECT
    country_code,
    application_kind,
    COUNT(1) application_kind_count
  FROM `patents-public-data.patents.publications`
  WHERE country_code IN (SELECT country_code FROM A)
  GROUP BY country_code, application_kind
), C AS (
  SELECT
    country_code,
    application_kind,
    application_kind_count,
    DENSE_RANK() OVER(PARTITION BY country_code ORDER BY application_kind_count DESC) AS application_kind_rank
  FROM B
)
SELECT
  country_code,
  application_kind,
  application_kind_count
FROM C
WHERE application_kind_rank <= 2  

И я получаю что-то вроде:

country_code     application_kind   count
JP               A                  125
JP               U                  124
CN               A                  118
CN               U                  101

Теперь я хотел бы добавить следующий поворот по оси Y: чтобы получить следующее:

  • Икс: первые 2 страны по количеству и в этих странах 2 лучших кода по количеству
  • Д: Топ 2 family_id по количеству, Top 2 priority_date по количеству

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

Выполнение кросс-поворота в Google BigQuery

Я могу построить Y-запрос во втором запросе --

WITH A AS (
  SELECT family_id
  FROM `patents-public-data.patents.publications`
  GROUP BY family_id
  ORDER BY COUNT(1) DESC
  LIMIT 2
), B AS (
  SELECT
    family_id,
    priority_date,
    COUNT(1) priority_date_count
  FROM `patents-public-data.patents.publications`
  WHERE family_id IN (SELECT family_id FROM A)
  GROUP BY family_id, priority_date
), C AS (
  SELECT
    family_id,
    priority_date,
    priority_date_count,
    DENSE_RANK() OVER(PARTITION BY family_id ORDER BY priority_date_count DESC) AS priority_date_rank
  FROM B
)
SELECT
  family_id,
  priority_date,
  priority_date_count
FROM C
WHERE priority_date_rank <= 2 

Однако я не совсем уверен, как объединить их вместе, в одном запросе или в двух.

так что это будет своего рода пересечение X и Y - верно? если так - должен быть простой случай

Mikhail Berlyant 30.05.2019 03:58

@MikhailBerlyant да, это правильно, не зная заранее опорных значений (т. Е. Вам нужно выполнить запрос агрегации, чтобы получить значения «ТОП»)

David542 30.05.2019 04:04
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
2
122
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ниже приведен стандартный SQL BigQuery, это просто демонстрация подхода, не претендующая на 100% представление запрошенной логики.

WITH A_X AS (
  SELECT country_code FROM `patents-public-data.patents.publications`
  GROUP BY country_code ORDER BY COUNT(1) DESC LIMIT 2
), B_X AS (
  SELECT country_code, application_kind, COUNT(1) application_kind_count
  FROM `patents-public-data.patents.publications` WHERE country_code IN (SELECT country_code FROM A_X)
  GROUP BY country_code, application_kind
), C_X AS (
  SELECT country_code, application_kind, application_kind_count,
    DENSE_RANK() OVER(PARTITION BY country_code ORDER BY application_kind_count DESC) AS application_kind_rank
  FROM B_X
), X AS (
  SELECT country_code, application_kind, application_kind_count
  FROM C_X WHERE application_kind_rank <= 2  
), A_Y AS (
  SELECT family_id FROM `patents-public-data.patents.publications` 
  JOIN X USING(country_code, application_kind)
  GROUP BY family_id 
  ORDER BY COUNT(1) DESC LIMIT 2
), B_Y AS (
  SELECT family_id, priority_date, COUNT(1) priority_date_count
  FROM `patents-public-data.patents.publications` WHERE family_id IN (SELECT family_id FROM A_Y) 
  GROUP BY family_id, priority_date
), C_Y AS (
  SELECT family_id, priority_date, priority_date_count,
    DENSE_RANK() OVER(PARTITION BY family_id ORDER BY priority_date_count DESC) AS pos_date
  FROM B_Y
), Y AS (
  SELECT family_id, priority_date, pos_date, DENSE_RANK() OVER(ORDER BY family_id) pos_family
  FROM C_Y WHERE pos_date <= 2 
)
SELECT country_code, application_kind,
  COUNTIF(pos_family = 1 AND pos_date = 1) `family1_date1`,
  COUNTIF(pos_family = 1 AND pos_date = 2) `family1_date2`,
  COUNTIF(pos_family = 2 AND pos_date = 1) `family2_date1`,
  COUNTIF(pos_family = 2 AND pos_date = 2) `family2_date2`
FROM `patents-public-data.patents.publications` 
JOIN Y USING(family_id, priority_date)
WHERE country_code IN (SELECT country_code FROM X)
AND application_kind IN (SELECT application_kind FROM x) 
GROUP BY country_code, application_kind 

результат

Очевидно, что сверху есть несколько нулей из-за логики пересечения

выглядит неплохо. Однако одно изменение, вместо того, чтобы говорить «family1_date1», можем ли мы сделать это фактическим значением «family1» и значением «date1»? Я могу пойти дальше и присудить награду позже. Хорошо сделано!

David542 01.06.2019 04:36

Это возможно только с динамическим SQL, где на первом этапе вы генерируете весь запрос с необходимыми псевдонимами на выходе, а затем на втором этапе вы фактически выполняете такой сгенерированный запрос. Здесь, на SO, есть много примеров такого подхода. Вы можете проверить мои недавние ответы - я помню, что у меня был аналогичный ответ день или несколько дней назад

Mikhail Berlyant 01.06.2019 04:41

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

David542 02.06.2019 02:12

@ David542 - это один из последних отвечать - там есть ссылка на еще один предыдущий ответ

Mikhail Berlyant 04.06.2019 02:42

Другие вопросы по теме

Похожие вопросы