使用 window 函数更新列
UPDATE column using a window function
我正在使用 PostgreSQL 9.3
我有一个名为 cat
的 table,其中包含以下三个感兴趣的列:
ID
、SOURCE
、TIME
ID
和 TIME
值是唯一的(即没有重复)但有几行具有相同的 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)
上的索引也可能有更好的性能;但是,这可能取决于数据中值的分布。
以上不处理 SOURCE
的 NULL
值,但这很容易处理:
WHERE cc.SOURCE IS NOT DISTINCT FROM c.SOURCE;
我正在使用 PostgreSQL 9.3
我有一个名为 cat
的 table,其中包含以下三个感兴趣的列:
ID
、SOURCE
、TIME
ID
和 TIME
值是唯一的(即没有重复)但有几行具有相同的 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)
上的索引也可能有更好的性能;但是,这可能取决于数据中值的分布。
以上不处理 SOURCE
的 NULL
值,但这很容易处理:
WHERE cc.SOURCE IS NOT DISTINCT FROM c.SOURCE;