以下是这两个表的 struct :

这是"主"表:

CREATE TEMP TABLE final_table (
    idx INTEGER,
    pids INTEGER[],
    stats INTEGER[]
)
INSERT INTO final_table
VALUES
    (2733111, '{43255890, 8653548}'::int[], '{4, 5}'::int[]),   
    (2733112, '{54387564}'::int[]         , '{6}'::int[]   ),   
    (2733113, '{}'::int[]                 , '{}'::int[]    )

以下是临时表中的数据:

CREATE TEMP TABLE aggreg (
    idx INTEGER,
    pid INTEGER,
    count INTEGER
)
VALUES
    (2733111, 21854997,  2),    
    (2733111, 21854923, 10),    
    (2733112, 12345689,  3),    
    (2733113, 98765348, 11),    
    (2733111, 43255890,  4),    
    (2733112, 54387564,  6);

目标是用临时表中的数据更新第一个表(FINAL_TABLE).

困难在于,在classic 的更新中,同一行将被调用多次,因此只有在更新中才会有最后的结果.因此,在UPDATEFROM号中必须经过一个SELECT号潜艇,而我就是被困在那里的.

我似乎在SELECT SUB中找不到正确的语法来执行此操作.

此外,在实际的表中,有些行可能已经在第pids列和第stats列中包含数据.此UPDATE的目的是仅添加pid及其对应的count.

我测试的最后一个查询(但没有运行)如下:

UPDATE final_table AS ft
    SET
        stats = ag2.stats || (ag2.stats - ft.stats),
        pids = ag2.pids || (ag2.pids - ft.pids)
FROM (
    SELECT
        ag.idx,
        array_agg(ag.pid) AS pids,
        array_agg(ag."count") AS stats
    FROM
            aggreg AS ag
    INNER JOIN
            final_table AS ft
    ON
            ag.idx = ft.idx
    GROUP BY
            ag.idx
) AS ag2
WHERE
    ag2.idx = ft.idx

另外,我使用intarray扩展来执行array - array操作.

根据示例表,我希望得到以下结果:

idx pids stats
2733111 {43255890, 8653548, 21854997, 21854923} {4, 5, 2, 10}
2733112 {54387564, 12345689} {6, 3}
2733113 {98765348} {11}

提前感谢您的帮助!

推荐答案

与在两个表之间使用JOIN运算并在UPDATE语句中使用它不同,您可以从"aggreg"表中构造数组,并在UPDATE语句的FROM ... WHERE ...子句中使用它,如下所示.

为了处理数组中的现有元素,您应该首先取消嵌套以前的数据,将其与aggreg数据合并,并相应地更新您的"final_table".

WITH full_data AS (
    SELECT * FROM aggreg
  
    UNION
  
    SELECT ft.idx,
           t.pids, 
           t.stats
    FROM final_table ft
    CROSS JOIN UNNEST(ft.pids, ft.stats) AS t(pids, stats)
), aggreg_data AS (
    SELECT idx, 
           ARRAY_AGG(pid ORDER BY pid)   AS pids, 
           ARRAY_AGG(count ORDER BY pid) AS counts
    FROM full_data
    GROUP BY idx
)
UPDATE final_table
SET pids = cte.pids,
    stats = cte.counts
FROM aggreg_data cte
WHERE final_table.idx = cte.idx;

Output:

idx pids stats
2733111 [21854997,21854923,8653548,43255890] [2,10,5,4]
2733112 [12345689,54387564] [3,6]
2733113 [98765348] [11]

查看演示here.

注意:ARRAY_AGG函数中的ORDER BY子句将确保保持数组之间的对应关系.如果需要精确的原始顺序,查询可能会变得更复杂、更繁重,因为这将需要一个rowid(用ROW_NUMBER计算)和另一个子查询.

Sql相关问答推荐

如何使用LinkHouse群组ArrayInsertAt以零作为位置参数

SQL从同一表连接列

如何使用PostGIS从单个表中 Select 所有相交面组

如何设计一个调用嵌套函数并仅在所有被调用的嵌套函数都提交时才提交的事务,例如,如果一个子函数失败则中止?

无法将发票与产品价格相关联

如何为缺少的类别添加行

排除具有部分匹配条件的记录

如何根据几个条件 Select 值:如果满足一个范围的SUM,则对另一个范围求和

计算不同模式的时间跨度

将最近的结束日期与开始日期相匹配

SQL SUM Filter逻辑解释

两个具有 NULL 值的表达式结果之间的差异

获取多个开始-结束时间戳集之间经过的时间

避免在SQL中使用具有相同条件的多个子查询

为什么在事务中未被后续使用的CTE执行SELECT...FOR UPDATE无效?

for each 客户查找每个类别的最新评分

将 MERGE 语句与 Oracle PL/SQL 表类型一起使用时,导致无效数据类型错误的原因是什么?

添加一列并根据其他列值进行填充

Select 给定类别列表(或更多类别)中的所有事物

使用 SQL 表中的连接列删除重复记录