【问题标题】:UPDATE column using a window function使用窗口函数更新列
【发布时间】:2019-10-26 10:26:02
【问题描述】:

我使用的是 PostgreSQL 9.3

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

IDSOURCETIME

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

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

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

返回以下错误: ERROR: window functions are not allowed in UPDATE

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

【问题讨论】:

    标签: sql postgresql sql-update aggregate-functions common-table-expression


    【解决方案1】:

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

    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
    

    【讨论】:

    • 谢谢!它工作得很好,考虑到我的桌子大小,它相当快(约 8 分钟)。再次感谢!
    【解决方案2】:

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

    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 匹配做出任何假设——您的问题没有指定表上的任何主键。在(SOURCE, TIME) 上的索引也可能具有更好的性能;但是,这可能取决于数据中值的分布。

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

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

    【讨论】:

      猜你喜欢
      • 2016-01-04
      • 1970-01-01
      • 2013-03-10
      • 1970-01-01
      • 2011-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多