Postgresql Postgres使用公共数组元素合并两行

Postgresql Postgres使用公共数组元素合并两行,postgresql,Postgresql,我有一个postgres表,列名为id +----+--------------+ | id | ids | +----+--------------+ | 1 | {1, 2, 3} | | 2 | {2, 7, 10} | | 3 | {14, 11, 1} | | 4 | {12, 13} | | 5 | {15, 16, 12} | +----+--------------+ 我想将行与至少一个公共数组元素合并,并从中创建新行或合并到一个

我有一个postgres表,列名为id

+----+--------------+
| 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}         |
+----+--------------------------+
结果表中数组元素的顺序并不重要,但它们必须是唯一的

这些行是独立于其他系统添加的。例如,我们可以添加一个新行,其中id为{16,18,1}

现在,为了确保我们将所有行与至少一个公共数组元素组合在一起,我正在我的server Node.js中进行计算

因此,在创建新行之前,我使用以下方法提取数据库中至少有一个共同项的所有现有行:

await t.any('SELECT * FROM arraytable WHERE $1 && ids', [16, 18, 1])
这给了我所有至少有16、18或1的行。然后我将行与[16,18,1]合并并删除重复项

有了这个新数组,我删除了上面获取的所有现有行,并将新行插入数据库。如您所见,大部分工作都是在Node.js中完成的

相反,我尝试创建一个触发器,它将在添加新行时为我执行所有这些步骤。我怎么用扳机来做这件事呢。此外,还有更好的方法吗?

给定的表格

CREATE TABLE table1(id serial, ids INT [] )
CREATE TABLE table2(id serial, ids INT [] )
扳机看起来是这样的


CREATE OR REPLACE FUNCTION sum_tables_trigger() RETURNS TRIGGER AS $table1$
   BEGIN
      INSERT INTO table2(ids) SELECT ARRAY(SELECT DISTINCT UNNEST(table1.ids || new.ids) ORDER BY 1) FROM table1 WHERE table1.ids && new.ids;
      RETURN NEW;
   END;
$table1$ LANGUAGE plpgsql;

CREATE TRIGGER sum_tables_trigger_ BEFORE INSERT ON table1
FOR EACH ROW EXECUTE PROCEDURE sum_tables_trigger();
如果表具有公共元素,则tableA.ids&&tableB.ids返回true

tableA.ids | | tableB.ids添加元素

ARRAYSELECT DISTINCT UNNESTtable1.ids | | new.ids ORDER BY 1删除重复项。

给定的表

CREATE TABLE table1(id serial, ids INT [] )
CREATE TABLE table2(id serial, ids INT [] )
扳机看起来是这样的


CREATE OR REPLACE FUNCTION sum_tables_trigger() RETURNS TRIGGER AS $table1$
   BEGIN
      INSERT INTO table2(ids) SELECT ARRAY(SELECT DISTINCT UNNEST(table1.ids || new.ids) ORDER BY 1) FROM table1 WHERE table1.ids && new.ids;
      RETURN NEW;
   END;
$table1$ LANGUAGE plpgsql;

CREATE TRIGGER sum_tables_trigger_ BEFORE INSERT ON table1
FOR EACH ROW EXECUTE PROCEDURE sum_tables_trigger();
如果表具有公共元素,则tableA.ids&&tableB.ids返回true

tableA.ids | | tableB.ids添加元素

ARRAYSELECT DISTINCT unnestable1.ids | | new.ids ORDER BY 1删除重复项。

过程是否足够

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;
不幸的是,在触发器中插入行会调用另一个触发器,从而导致无穷循环。我不知道如何解决这个问题

另外,如果创建另一个答案是错误的做法,请道歉。我想暂时把它留作参考。问题解决后,我将删除它

由pewpewlasers编辑:

为了防止循环,可能需要另一个表。我已经创建了一个新的临时表2。可以将新数组添加到此表中。此表将有一个触发器,用于执行计算并将其保存到表1中。它还将删除此临时创建的行

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();
程序够了吗

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;
不幸的是,在触发器中插入行会调用另一个触发器,从而导致无穷循环。我不知道如何解决这个问题

另外,如果创建另一个答案是错误的做法,请道歉。我想暂时把它留作参考。问题解决后,我将删除它

由pewpewlasers编辑:

为了防止循环,可能需要另一个表。我已经创建了一个新的临时表2。可以将新数组添加到此表中。此表将有一个触发器,用于执行计算并将其保存到表1中。它还将删除此临时创建的行

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();

如果没有表1怎么办?我会修改问题以避免混淆。如果没有表1怎么办?我将修改问题以避免混淆。非常感谢Robert,使用你的两个答案,我创建了一个解决我问题的编辑。再次感谢!非常感谢罗伯特,利用你的两个答案,我创建了一个编辑,解决了我的问题。再次感谢!