postgresql - Postgres 用公共数组元素合并两行
问题描述
我有一个列名为“ids”的 postgres 表。
+----+--------------+
| id | ids |
+----+--------------+
| 1 | {1, 2, 3} |
| 2 | {2, 7, 10} |
| 3 | {14, 11, 1} |
| 4 | {12, 13} |
| 5 | {15, 16, 12} |
+----+--------------+
我想将行与至少一个公共数组元素合并,并从中创建一个新行(或合并到一个现有行中)。所以最终表格如下所示:
+----+--------------------------+
| id | ids |
+----+--------------------------+
| 6 | {1, 2, 3, 7, 10, 14, 11} |
| 7 | {12, 13, 15, 16} |
+----+--------------------------+
结果表中数组元素的顺序并不重要,但它们必须是唯一的。
这些行是独立于另一个系统添加的。例如,我们可以在 ids 的位置添加一个新行{16, 18, 1}
。
现在,为了确保我们将所有行与至少一个公共数组元素组合在一起,我正在我的服务器 (Node.js) 中进行计算。
因此,在创建新行之前,我使用以下方法提取数据库中至少有一个共同项目的所有现有行:
await t.any('SELECT * FROM arraytable WHERE $1 && ids', [16, 18, 1])
这给了我所有至少有 16、18 或 1 的行。然后我将这些行与 [16、18、1] 合并并删除重复项。
随着这个新数组的可用性,我删除了上面提取的所有现有行并将这个新行插入到数据库中。如您所见,大部分工作都是在 Node.js 中完成的。
而不是这个,我试图创建一个触发器,它会在我添加新行后立即为我完成所有这些步骤。我该如何使用触发器来执行此操作。另外,有没有更好的方法?
解决方案
手续够吗?
CREATE OR REPLACE PROCEDURE add_ids(new_ids INT[])
AS $$
DECLARE sum_array INT[];
BEGIN
SELECT ARRAY (SELECT UNNEST(ids) FROM table1 WHERE table1.ids && new_ids) INTO sum_array;
sum_array := sum_array || new_ids;
SELECT ARRAY(SELECT DISTINCT UNNEST(sum_array)) INTO sum_array;
DELETE FROM table1 WHERE table1.ids && sum_array;
INSERT INTO table1(ids) SELECT sum_array;
END;
$$
LANGUAGE plpgsql;
不幸的是,在触发器中插入行会调用另一个触发器,从而导致无限循环。我不知道解决这个问题。
PS。抱歉,如果创建另一个答案是不好的做法。我想暂时留下它以供参考。问题解决后我会删除它。
由 pewpewlasers 编辑:
为了防止循环,可能需要另一个表。我创建了一个新的临时table2
. 可以将新数组添加到此表中。该表将有一个触发器,它进行计算并将其保存到table1
. 它还会删除这个临时创建的行。
CREATE OR REPLACE FUNCTION on_insert_temp() RETURNS TRIGGER AS $f$
DECLARE sum_array BIGINT[];
BEGIN
SELECT ARRAY (SELECT UNNEST(ids) FROM table1 WHERE table1.ids && NEW.ids) INTO sum_array;
sum_array := sum_array || NEW.ids;
SELECT ARRAY(SELECT DISTINCT UNNEST(sum_array)) INTO sum_array;
DELETE FROM table1 WHERE table1.ids && sum_array;
INSERT INTO table1(ids) SELECT sum_array;
DELETE FROM table2 WHERE id = NEW.id;
RETURN OLD;
END
$f$ LANGUAGE plpgsql;
CREATE TRIGGER on_insert_temp AFTER INSERT ON table2 FOR EACH ROW EXECUTE PROCEDURE on_insert_temp();
推荐阅读
- python - 在 Pycharm 中的 Python 和 R 之间共享数据
- javascript - 如何使用客户端 JS 基于现有文本从 Google 的 Cloud Natural Language API 获取 JSON?
- c++ - 如何使用 istream_iterator 将 unsigned char 向量转换为字符串?
- javascript - 我不能使用地图函数 TypeError:无法读取未定义的属性“地图”
- powershell - 在已创建的 hyper-v 虚拟机上重新安装相同或不同的操作系统
- java - 无法使用 HTTPS 连接到套接字
- c# - 使用后台工作者的函数调用
- mysql - 如何从 cart_items 表中获取添加在一起的项目
- povray - POV-Ray:颜料声明中的函数有什么作用?
- c# - 如何通过在 C# 中拖动其主体来移动绘制的图形?