2012-07-21 68 views
2

我想弄清楚如何填寫一列中缺少的值與來自給定列上具有相同值的其他行的非缺省值。例如,在下面的示例中,我希望所有的「1」的值等於鮑勃和所有的「2」的值等於約翰在postgresql中,如何填寫列中的缺失值?

ID # | Name 
-------|----- 
1  | Bob 
1  | (null) 
1  | (null) 
2  | John 
2  | (null) 
2  | (null) 
` 

編輯:有一點需要注意的是,我使用PostgreSQL 8.4和Greenplum不支持相關的子查詢。

+0

請說出您的「特定實施」。你使用什麼版本?另外,是否可以存在具有多個不同名稱的ID?如何處理?首先按字母順序選擇? – 2012-07-21 18:16:22

+0

@dchandler:Postgres 8.4 *不支持相關的子查詢(實際上已經這麼做了)。那麼Greenplum必須基於一個真正的舊版本。 – 2012-07-21 21:19:10

+0

@a_horse_with_no_name,這很有趣。那看起來就是Greenplum!多麼可恥 – 2012-07-22 21:58:03

回答

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; 
+0

我在一個不支持相關子查詢的特定實現上。有沒有其他的方法來處理它? – 2012-07-21 04:44:33

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; 

NO TE:如果給定ID存在多個名稱,則此查詢將失敗。 (並且它不會觸及其中存在非空名稱的

如果您的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
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單獨做這項工作是不是需要額外的聚合

如果是mul ti32的值爲name,按字母順序排列的第一個值(根據當前語言環境)被挑選 - 這就是ORDER BY id, name的用途。如果name毫不含糊,您可以省略該行。

此外,如果每個id至少有一個非空值,則可以省略WHERE name IS NOT NULL