我正在尝试弄清楚如何使用来自给定列上具有相同值的其他行的非缺失值来填充一列中缺少的值。例如,在下面的示例中,我希望所有“1”值等于Bob,并且所有“2”值都等于John
ID # | Name
-------|-----
1 | Bob
1 | (null)
1 | (null)
2 | John
2 | (null)
2 | (null)
`
编辑:有一点需要注意,我正在使用带有Greenplum的postgresql 8.4,因此不支持相关的子查询。
答案 0 :(得分:2)
CREATE TABLE bobjohn
( ID INTEGER NOT NULL
, zname varchar
);
INSERT INTO bobjohn(id, zname) VALUES
(1,'Bob') ,(1, NULL) ,(1, NULL)
,(2,'John') ,(2, NULL) ,(2, NULL)
;
UPDATE bobjohn dst
SET zname = src.zname
FROM bobjohn src
WHERE dst.id = src.id
AND dst.zname IS NULL
AND src.zname IS NOT NULL
;
SELECT * FROM bobjohn;
注意:如果给定Id存在多个名称,则此查询将失败。 (并且它不会触及 no 非空名称存在的记录)
如果您使用的是postgres版本> -9,则可以使用CTE来获取源元组(这相当于子查询,但更容易编写和读取(恕我直言).CTE也处理重复价值问题(以相当粗略的方式):
--
-- CTE's dont work in update queries for Postgres version below 9
--
WITH uniq AS (
SELECT DISTINCT id
-- if there are more than one names for a given Id: pick the lowest
, min(zname) as zname
FROM bobjohn
WHERE zname IS NOT NULL
GROUP BY id
)
UPDATE bobjohn dst
SET zname = src.zname
FROM uniq src
WHERE dst.id = src.id
AND dst.zname IS NULL
;
SELECT * FROM bobjohn;
答案 1 :(得分:1)
UPDATE tbl
SET name = x.name
FROM (
SELECT DISTINCT ON (id) id, name
FROM tbl
WHERE name IS NOT NULL
ORDER BY id, name
) x
WHERE x.id = tbl.id
AND tbl.name IS NULL;
DISTINCT ON
独自完成工作。不需要额外的聚合。
如果name
有多个值,则会选择按字母顺序排列的第一个(根据当前区域设置) - 这就是ORDER BY id, name
的用途。如果name
明确无误,则可以省略该行。
此外,如果每个id
至少有一个非空值,则可以省略WHERE name IS NOT NULL
。
答案 2 :(得分:0)
如果您知道的事实没有冲突的值(多个行具有相同的ID但不同的非空名称),那么这样的内容将适当地更新表:
UPDATE some_table AS t1
SET name = (
SELECT name
FROM some_table AS t2
WHERE t1.id = t2.id
AND name IS NOT NULL
LIMIT 1
)
WHERE name IS NULL;
如果您只想查询表并动态填写此信息,则可以使用类似的查询:
SELECT
t1.id,
(
SELECT name
FROM some_table AS t2
WHERE t1.id = t2.id
AND name IS NOT NULL
LIMIT 1
) AS name
FROM some_table AS t1;