Самостоятельное объединение вложенных записей в BigQuery - PullRequest
1 голос
/ 04 февраля 2020

Я пытаюсь сделать несколько объединений / агрегаций между вложенными полями в одной таблице и сталкиваюсь с обеими проблемами SQL и "Коррелированные подзапросы, которые ссылаются на другие таблицы, не поддерживаются, если они не могут быть декоррелированы, например превращая их в эффективную ошибку "JOIN".

Я бы хотел SQL помочь с общей проблемой, но мне также любопытно, как справиться с этой ошибкой.

Мой проблема сопоставляется с данными BigQuery о патентах . В этом наборе данных патент имеет данные классификации (запись cpc, где cpc.code - это один код классификации в записи со связанными данными cpc.inventive и cpc.first). Патент также имеет патенты, на которые он ссылается (запись citation, где citation.publication_number - цитируемый патент со связанными данными citation.type и citation.category). В этих записях есть больше полей, но, скажем, это важные.

Я хочу получить что-то вроде json, с одной строкой на CP C и записью с информацией, которая захватывает как патенты с этим CP C цитируют другие патенты, основанные на ценах за клик, на цитируемых патентах и ​​аспектах как о ценах за клик, так и о цитировании. json будет выглядеть примерно так:

[
  {
      "citing_patent_cpc": "1234/123",
      "cited_patent_cpcs":
      [
        {
          "cpc": "ABCD/345",
          "citing_cpc_inventive": true,
          "citing_cpc_first": false,
          "citation_type": "ABC",
          "citation_category": "A",
          "cited_cpc_inventive": false,
          "cited_cpc_first": true,
          "count": 45
        },
        {
          "cpc": "ABCD/345",
          "citing_cpc_inventive": true,
          "citing_cpc_first": false,
          "citation_type": "ABC",
          "citation_category": "A",
          "cited_cpc_inventive": false,
          "cited_cpc_first": false,
          "count": 12
        },
        {
          "cpc": "H211/123",
          "citing_cpc_inventive": true,
          "citing_cpc_first": false,
          "citation_type": "ABC",
          "citation_category": null,
          "cited_cpc_inventive": true,
          "cited_cpc_first": false,
          "count": 3
        },
        ...

      ]
  },
  {
      "citing_patent_cpc": "1234/ABC",
      "cited_patent_cpcs":
      [
        {
          "cpc": "ABCD/345",
          "citing_cpc_inventive": true,
          "citing_cpc_first": false,
          "citation_type": "ABC",
          "citation_category": "A",
          "cited_cpc_inventive": false,
          "cited_cpc_first": true,
          "count": 16
        },
        {
          "cpc": "ABCD/345",
          "citing_cpc_inventive": true,
          "citing_cpc_first": false,
          "citation_type": "ABC",
          "citation_category": "A",
          "cited_cpc_inventive": false,
          "cited_cpc_first": false,
          "count": 3
        },
        {
          "cpc": "H211/123",
          "citing_cpc_inventive": true,
          "citing_cpc_first": false,
          "citation_type": "ABC",
          "citation_category": null,
          "cited_cpc_inventive": true,
          "cited_cpc_first": false,
          "count": 9
        },
        ...
      ]
  },
  ...
]

Где каждый уникальный cpc.code получает строку и массив. Массив представляет собой записи с информацией о количестве патентов, процитированных патентами в строке CP C ("citing_patent_cp c"), имеющей спецификацию c CP C ("cp c") с различными аспектами CPC двух патентов и тип цитирования.

Например, первая запись в приведенном выше примере означает, что в 45 раз патенты с CP C "1234/123" в качестве изобретательского CP C но не первый CP C процитировал другой патент с CP c "ABCD / 345" в качестве первого CP C, но не CP C по изобретению, и эта цитата была типа "AB C" и категория "А". Теоретически, каждая строка может иметь запись для каждого CP C в корпусе * количество возможных граней, хотя на практике это не так.

В качестве частичного шага я попытался присоединиться к cp c записей из цитируемых патентов в записи для цитирующего патента. Я получил этот запрос для работы с очень маленькой таблицей, объявленной непосредственно в SQL, но он дает «Коррелированные подзапросы, которые ссылаются на другие таблицы, не поддерживаются, если они не могут быть декоррелированы, например, путем преобразования их в эффективный JOIN. " когда я пытаюсь запустить его на больших данных (как фактическая таблица патентов).

Вот этот запрос:

SELECT
  publication_number,
  cpc,
  citation,
  (
    SELECT ARRAY_CONCAT_AGG(cpc)
    FROM `patents-public-data.patents.publications` AS JoinedPatents
    RIGHT JOIN
      (
        SELECT publication_number
        FROM UNNEST(Patents.citation)
      ) AS unnestedcitation
    ON unnestedcitation.publication_number = JoinedPatents.publication_number) AS cited_cpc
FROM `patents-public-data.patents.publications`AS Patents

Мне бы хотелось знать:

  1. Как заставить этот запрос работать без этой ошибки.
  2. Общее решение моей проблемы, если кто-то чувствует себя щедрым с SQL -fu.

Спасибо всем, кто прочитал это далеко.

1 Ответ

2 голосов
/ 05 февраля 2020

Я думаю, что это должно быть близкое приближение для запроса, который вы хотите. Похоже, это большой набор данных, поэтому я не могу комментировать скорость / эффективность. Надеюсь, логика c имеет смысл как минимум.

with data as (
-- unnest your data
  select 
    p.publication_number,
    cp.code as cpc_code,
    cp.inventive as cpc_inventive,
    cp.first as cpc_first,
    ci.publication_number as citation_publication_number,
    ci.type as citation_type,
    ci.category as citation_category
  from `patents-public-data.patents.publications` p
  left join unnest(cpc) cp
  left join unnest(citation) ci
),
joined as (
-- do a self-join to join citation publication_number to original publication_number, group to get counts
  select 
    d1.cpc_code as citing_patent_cpc,
    d2.cpc_code as cpc,
    d1.cpc_inventive as citing_cpc_inventive,
    d1.cpc_first as citing_cpc_first,
    d1.citation_type,
    d1.citation_category,
    d2.cpc_inventive as cited_cpc_inventive,
    d2.cpc_first as cited_cpc_first,
    count(*) as count
  from data d1
  left join data d2 on d1.citation_publication_number = d2.publication_number
  group by 1,2,3,4,5,6,7,8
),
agged as (
-- aggrecate to match requested output
  select 
    citing_patent_cpc,
    array_agg(struct(cpc,citing_cpc_inventive,citing_cpc_first,citation_type,citation_category,cited_cpc_inventive,cited_cpc_first,count)) cited_patent_cpcs
  from joined
  group by 1
)
select * from agged
...