Идентификаторы перекрестных совпадений SQL для создания нового межплатформенного идентификатора -> как оптимизировать - PullRequest
2 голосов
/ 23 мая 2019

У меня есть таблица Redshift с двумя столбцами, которая показывает, какие идентификаторы связаны, то есть принадлежат одному человеку. Я хотел бы сделать сопоставление (дополнительный столбец) с уникальным идентификатором человека с помощью SQL.

Проблема похожа на эту: SQL: создание уникального идентификатора для элемента с несколькими идентификаторами

Однако в моем случае идентификаторы в обоих столбцах имеют различный вид, и поэтому предлагаемое объединяющее решение (t1.epid = t2.pid и т. Д.) Не будет работать.

В приведенном ниже примере 4 отдельных лица используют 9 идентификаторов типа 1 и 10 идентификаторов типа 2.

ID_type1 | ID_type2 
---------+--------
1        | A
1        | B
2        | C
3        | C
4        | D
4        | E
5        | E
6        | F
7        | G
7        | H
7        | I
8        | I
8        | J
9        | J
9        | B

Я ищу дополнительный столбец с привязкой к уникальному идентификатору человека. Трудность заключается в правильной идентификации идентификаторов, связанных с такими людьми, как x & z, которые имеют несколько идентификаторов обоих типов. Результат может выглядеть примерно так:

ID_type1 | ID_type2 | ID_real
---------+---------------------
1        | A        | z
1        | B        | z
2        | C        | y
3        | C        | y
4        | D        | x
4        | E        | x
5        | E        | x
6        | F        | w
7        | G        | z
7        | H        | z
7        | I        | z
8        | I        | z
8        | J        | z
9        | J        | z
9        | B        | z

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

WITH
T1 AS(
SELECT DISTINCT
       l1.ID_type1 AS ID_type1,
       r1.ID_type1 AS ID_type1_overlap
  FROM      crossmatch_example l1
  LEFT JOIN crossmatch_example r1 USING(ID_type2)
 ORDER BY 1,2
),

T2 AS(
SELECT DISTINCT
       l1.ID_type1,
       r1.ID_type1_overlap
  FROM      T1 l1
  LEFT JOIN T1 r1 on l1.ID_type1_overlap = r1.ID_type1
 ORDER BY 1,2
),

T3 AS(
SELECT DISTINCT
       l1.ID_type1,
       r1.ID_type1_overlap
  FROM      T2 l1
  LEFT JOIN T2 r1 on l1.ID_type1_overlap = r1.ID_type1
 ORDER BY 1,2
),

T4 AS(
SELECT DISTINCT
       l1.ID_type1,
       r1.ID_type1_overlap
  FROM      T3 l1
  LEFT JOIN T3 r1 on l1.ID_type1_overlap = r1.ID_type1
 ORDER BY 1,2
),

mapping AS(
SELECT ID_type1,
       min(ID_type1_overlap) AS mapped
  FROM T4
 GROUP BY 1
 ORDER BY 1
),

output AS(
SELECT DISTINCT
       l1.ID_type1::INT AS ID_type1,
       l1.ID_type2,
       FUNC_SHA1(r1.mapped) AS ID_real
  FROM crossmatch_example l1
  LEFT JOIN mapping       r1 on l1.ID_type1 = r1.ID_type1
 ORDER BY 1,2)

SELECT * FROM output

1 Ответ

0 голосов
/ 24 мая 2019

То, что вы пытаетесь сделать, называется Транзитивное замыкание .Есть статьи о том, как реализовать это в SQL.

Это пример Spark linq-like dsl https://github.com/apache/spark/blob/master/examples/src/main/scala/org/apache/spark/examples/SparkTC.scala.

Решение проблемы является итеративным, и для полного разрешения графа вам может потребоваться применить больше итераций,Что может быть оптимизировано, так это ввод для каждой итерации.Я помню, как работал над этим один раз, но не могу вспомнить детали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...