【发布时间】:2013-03-08 20:48:04
【问题描述】:
我正在尝试使用同一表中另一行的值更新表上的 多个列:
CREATE TEMP TABLE person (
pid INT
,name VARCHAR(40)
,dob DATE
,younger_sibling_name VARCHAR(40)
,younger_sibling_dob DATE
);
INSERT INTO person VALUES (pid, name, dob)
(1, 'John', '1980-01-05'),
(2, 'Jimmy', '1975-04-25'),
(3, 'Sarah', '2004-02-10'),
(4, 'Frank', '1934-12-12');
任务是在younger_sibling_name 和younger_sibling_dob 中填入与他们年龄最接近但不比他们大或同龄的人的姓名和出生日期。
我可以轻松设置弟弟dob,因为这是确定要与相关子查询一起使用的记录的值(我认为这是一个例子?):
UPDATE person SET younger_sibling_dob=(
SELECT MAX(dob)
FROM person AS sibling
WHERE sibling.dob < person.dob);
我只是看不到任何获取name的方法?
对于每个 MAX 选择,实际查询将运行大约 1M 记录,每组 100-500 条记录,因此性能是一个问题。
编辑:
在尝试了许多不同的方法后,我决定采用我认为不错的方法 能够用中间结果验证数据的平衡,表明 逻辑的意图,并充分执行:
WITH sibling AS (
SELECT person.pid, sibling.dob, sibling.name,
row_number() OVER (PARTITION BY person.pid
ORDER BY sibling.dob DESC) AS age_closeness
FROM person
JOIN person AS sibling ON sibling.dob < person.dob
)
UPDATE person
SET younger_sibling_name = sibling.name
,younger_sibling_dob = sibling.dob
FROM sibling
WHERE person.pid = sibling.pid
AND sibling.age_closeness = 1;
SELECT * FROM person ORDER BY dob;
【问题讨论】:
-
顺便说一句:如果您对性能如此着迷,您可以存储
sibling_id REFERENCES person(pid)而不是重复的 {sibling_name,sibling_dob}
标签: sql postgresql sql-update correlated-subquery window-functions