Sql 聚合行以获得不带子集的唯一数组

Sql 聚合行以获得不带子集的唯一数组,sql,postgresql,merge,concatenation,postgresql-performance,Sql,Postgresql,Merge,Concatenation,Postgresql Performance,初始数据实际表包含超过2000000行: +--------+--------+-------+ | note | factor | label | +--------+--------+-------+ | note_1 | 1 | 2 | +--------+--------+-------+ | note_1 | 1 | 3 | +--------+--------+-------+ | note_1 | 2 | 4 | +----

初始数据实际表包含超过2000000行:

+--------+--------+-------+
| note   | factor | label |
+--------+--------+-------+
| note_1 | 1      | 2     |
+--------+--------+-------+
| note_1 | 1      | 3     |
+--------+--------+-------+
| note_1 | 2      | 4     |
+--------+--------+-------+
| note_2 | 123    | 2     |
+--------+--------+-------+
| note_2 | 123    | 3     |
+--------+--------+-------+
| note_2 | 2      | 4     |
+--------+--------+-------+
| note_3 | 456    | 4     |
+--------+--------+-------+
| note_4 | 434    | 5     |
+--------+--------+-------+
| note_5 | 456    | 3     |
+--------+--------+-------+
| note_5 | 456    | 4     |
+--------+--------+-------+
我想要得到的是进一步的最终表格:

更清楚地说:

我需要按因子和标签列对注释进行分组。注释只能在结果表中显示一次。结果表应该包含两列:id-行号,注释-注释数组

我已经向group by factor and label编写了一个查询:

选择“按系数排序”上的行号作为id ,数组_agg注释按注释顺序排列为注释 来自test_品牌 按因子分组,标签 它给出了以下结果:

+---+-----------------+
| 1 | {note_1}        |
+---+-----------------+
| 2 | {note_1}        |
+---+-----------------+
| 3 | {note_2}        |
+---+-----------------+
| 4 | {note_2}        |
+---+-----------------+
| 5 | {note_1,note_2} |
+---+-----------------+
| 6 | {note_4}        |
+---+-----------------+
| 7 | {note_5}        |
+---+-----------------+
| 8 | {note_3,note_5} |
+---+-----------------+
但我不知道如何从这里开始进行最后的谈判

如果我们省略标识符并返回到普通数字,那么这个任务看起来就像一个集合的并集,实际上它是。 假设我们有8个集合:{1},{1},{2},{1,2},{4},{5},{3,5}。我们需要得到三个集合:{1,2},{4},{3,5}

我认为这是怎么发生的: 集合{1}、{1}、{2}、{2}、{1,2}合并为一个集合{1,2},因为{1}和{2}与{1,2}之间存在交集。 集合{3,5},{5}合并为一个集合{3,5},因为{5}和{3,5}之间存在交集。
集合{4}不与任何人相交,因此它保持原样。

可能有更有效的方法,但这样做:

以cte为例 选择minrn作为rn,notes-以低成本删除重复 从…起 选择按因子排序的行数,标签为rn-按因子排序,标签?! ,数组_agg注释按注释顺序排列为注释 来自test_品牌 按因子分组,标签 附属的 按注释分组 选择按rn排序的行编号作为rn,注释 来自cte c 不存在的地方 从cte c1中选择 其中c1.notes@>c.notes 和c1.rn c.rn 1号订单; 小提琴

初始查询后,删除CTE中的重复项并记住最小行数

在最终选择中,删除该集合包含在除自身之外的其他集合中的所有行。使用另一个row_number实例压缩行号。 瞧

优化性能 200多万行

如果note可以是整数而不是字符串类型,那么计算速度将大大加快,在安装额外的模块后更是如此,该模块为整数数组提供了更快的@>运算符实现

如果来自CTE的派生表仍然很大,那么创建一个临时表、添加一个索引并进行分析是值得的!,并根据该临时表运行外部选择:

将临时表tmp创建为 选择minrn作为rn,notes-以低成本删除重复 从…起 选择按系数排序的行数,标签为rn ,数组_agg注释按注释顺序排列为注释 来自test_品牌 按因子分组,标签 附属的 按注释分组 ; 使用gin notes gin\uuu int\u ops在tmp上创建索引; 分析tmp; 选择按rn排序的行编号作为rn,注释 来自tmp c 不存在的地方 从tmp c1中选择 其中c1.notes@>c.notes 和c1.rn c.rn 1号订单; 见:


谢谢你的回答!我不确定,但出了点问题。您可以在这里看到运行示例:我只添加了两个新行:note_7、123、2和note_8、656、8。正确的结果是:{note_1,note_2,note_7}{note_4}{note_3,note_5}{note_8},但是运行脚本会得到以下结果:{note_1,note_2}{note_2,note_7}{note_4}{note_3,note_5}{note_8}@ErwinBrandstetter。不知何故,你开始回答可能有更有效的方法是认知不协调。几乎从定义上讲,我希望你的答案是在博士后做事情的最有效的方式。@Moon但是note_1和note_7没有共享因子,label?@Gordon:这次我不太确定。@>这是一个没有索引的昂贵操作。关于优化的补充对我来说更好。不过,我觉得可能有更多的潜力来加速。而且,谢谢你。@ErwinBrandstetter,是的,他们不是。但是注释1共享因子,标签为注释2,注释2共享因子,标签为注释7。然后我们需要把他们都聚在一起。换句话说:{1},{1,2},{2,7}应该创建一组{1,2,7}。
+---+-----------------+
| 1 | {note_1}        |
+---+-----------------+
| 2 | {note_1}        |
+---+-----------------+
| 3 | {note_2}        |
+---+-----------------+
| 4 | {note_2}        |
+---+-----------------+
| 5 | {note_1,note_2} |
+---+-----------------+
| 6 | {note_4}        |
+---+-----------------+
| 7 | {note_5}        |
+---+-----------------+
| 8 | {note_3,note_5} |
+---+-----------------+