2

ある列に欠落している値を、特定の列に同じ値を持つ他の行の欠落していない値で埋める方法を見つけようとしています。たとえば、以下の例では、すべての「1」の値をボブと等しくし、すべての「2」の値をジョンと等しくしたいと思います。

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

編集: 1 つの注意点は、Greenplum で postgresql 8.4 を使用しているため、相関サブクエリがサポートされていないことです。

4

3 に答える 3

3
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に複数の名前が存在する場合、このクエリは失敗します。( null以外の名前が存在しないレコードには影響しません)

postgresバージョン>-9を使用している場合は、CTEを使用してソースタプルをフェッチできます(これはサブクエリと同等ですが、書き込みと読み取りが簡単です(IMHO)。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;
于 2012-07-21T11:51:56.473 に答える
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は、その行を省略できます。

また、 ごとに null 以外の値が少なくとも 1 つある場合はid、 を省略できますWHERE name IS NOT NULL

于 2012-07-21T18:26:14.807 に答える
0

競合する値 (ID が同じで名前が null でない複数の行) がないことがわかっている場合は、次のようにしてテーブルを適切に更新します。

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;
于 2012-07-21T04:07:47.347 に答える