使用 window 函数更新列

UPDATE column using a window function

我正在使用 PostgreSQL 9.3

我有一个名为 cat 的 table,其中包含以下三个感兴趣的列:

IDSOURCETIME

IDTIME 值是唯一的(即没有重复)但有几行具有相同的 SOURCE

我想更新 SOURCE 列的每个值,将其设置为具有相同 SOURCE 值的每组行中第一个输入行的 ID 值并按 TIME 升序排列。

SELECT 语句中,我会使用:

SELECT
first_value(ID) OVER (PARTITION BY SOURCE ORDER BY TIME ASC) AS SOURCE
FROM cat;

所以我为 UPDATE 语句尝试了这个:

UPDATE cat
SET SOURCE = first_value(ID) OVER (PARTITION BY SOURCE ORDER BY TIME ASC);

其中returns出现如下错误: ERROR: window functions are not allowed in UPDATE

考虑到 cat 有大约 800 000 行和 322 列,有人可以帮我找到一个快速的方法吗?

您可以使用普通的 table 表达式来计算新值,然后将新值应用于原始 table,例如:

with cte as (
    select      
        id, 
        time,
        first_value(id) over (partition by source order by time asc) as source
    from cat
)
update cat set cat.source = cte.source
from cte
where cte.id = cat.id and cte.time = cat.time

我会使用聚合(本质上)而不是window函数来表达这个:

UPDATE cat c
    SET SOURCE = cc.ID
    FROM (SELECT DISTINCT ON (SOURCE) c.*
          FROM cat
          ORDER BY SOURCE, TIME
         ) cc
    WHERE cc.SOURCE = c.SOURCE;

这更安全,因为它不会在数据中对行上的 1-1 匹配做出任何假设——您的问题没有在 table 上指定任何主键。它在 (SOURCE, TIME) 上的索引也可能有更好的性能;但是,这可能取决于数据中值的分布。

以上不处理 SOURCENULL 值,但这很容易处理:

    WHERE cc.SOURCE IS NOT DISTINCT FROM c.SOURCE;