SQL 交叉匹配 ID 以创建新的跨平台 ID -> 如何优化
Posted
技术标签:
【中文标题】SQL 交叉匹配 ID 以创建新的跨平台 ID -> 如何优化【英文标题】:SQL cross match IDs to create new cross-platform ID -> how to optimize 【发布时间】:2019-10-10 04:32:53 【问题描述】:我有一个 Redshift 表,其中有两列显示哪些 ID 已连接,即属于同一个人。我想使用 SQL 制作具有唯一人员 ID 的映射(额外列)。
问题和这个类似:SQL: creating unique id for item with several ids
但是在我的情况下,两列中的 ID 是不同类型的,因此建议的加入解决方案(t1.epid = t2.pid 等)将不起作用。
在下面的示例中,有 4 个个人使用 9 个类型 1 的 ID 和 10 个类型 2 的 ID。
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
我正在寻找的是一个额外的列,其中映射到该人的唯一 ID。困难在于正确识别与 x 和 z 等具有两种类型的多个 ID 的人相关的 ID。结果可能如下所示:
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
【问题讨论】:
这种类型的操作通常使用递归 CTE,Redshift 不支持。在您的示例中,您只需遍历一个“链接”。但是,如果你有“9/A, 9/I”,你的结果就会完全不同。 总遍历次数未知(编辑示例以更好地反映这一点)。由于不支持递归 CTE,我将不得不手动添加步骤,并查看不同 ID_real 的数量何时不会进一步显着减少。 我添加了我的查询,它可以为小型数据集完成工作(参见示例),但是对于大型数据集(+100k 行),它确实很困难(不工作)。 @GordonLinoff 有什么建议如何利用 redshift 以高效/有效的方式做到这一点? 【参考方案1】:您正在尝试做的事情称为传递闭包。有关于如何在 SQL 中实现它的文章。
这是 Spark linq-like dsl https://github.com/apache/spark/blob/master/examples/src/main/scala/org/apache/spark/examples/SparkTC.scala 中的一个示例。
问题的解决方案是迭代的,要完全解决图形,您可能需要应用更多的迭代。可以优化的是每次迭代的输入。我记得曾经做过一次,但不记得细节了。
【讨论】:
以上是关于SQL 交叉匹配 ID 以创建新的跨平台 ID -> 如何优化的主要内容,如果未能解决你的问题,请参考以下文章