2012-07-21 6 views
2

주어진 열에 같은 값을 가진 다른 행의 누락되지 않은 값으로 한 열에서 누락 된 값을 채우는 방법을 알아 내려고하고 있습니다. 예를 들어, 아래의 예에서, 내가 요한에게 동일하게 모두 "1"값은 밥과 "2"모든 값과 동일 할 것postgresql에서 열에 누락 된 값을 어떻게 채울 수 있습니까?

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

편집 : 하나주의해야 할 점은입니다 I 'Greenplum과 함께 postgresql 8.4를 사용하기 때문에 상관 관계가있는 서브 쿼리는 지원되지 않습니다.

+0

"특정 구현"이라고 지정하십시오. 어떤 버전을 사용합니까? 또한 하나 이상의 고유 한 이름을 가진 ID의 경우가있을 수 있습니까? 어떻게 처리할까요? 알파벳순으로 먼저 선택하셨습니까? –

+0

@dchandler : Postgres 8.4 *는 상관 하위 쿼리를 지원합니다 (실제로 연령대별로 수행 했음). Greenplum은 정말 오래된 버전을 기반으로해야합니다. –

+0

@a_horse_with_no_name, 재미 있습니다. 다음 Greenplum 것 같습니다! 얼마나 수치스러운가요? –

답변

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

NO : 당신은 단지 테이블을 조회 할 및 즉시 채워이 정보가있는 경우, 당신은 유사한 쿼리를 사용할 수 있습니다 TE : 주어진 ID에 대해 하나 이상의 이름이 존재하면이 쿼리는 실패합니다. 당신이 포스트 그레스 버전> -9에있는 경우, 당신은 소스 튜플을 가져 오기 위해 CTE를 사용할 수

(그리고 더 null 이외의 이름이 존재하지 않는 에 대한 기록을 터치하지 않습니다) (이것은 동일합니다 . 하위 쿼리는하지만, CTE는 (다소 원유 방법) 중복 값-문제를 다룹 작성하고 (IMHO) 읽기 쉽게 :.

 -- 
     -- 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 혼자 일을하지 추가에 필요한 집합 (aggregation)

mul name에 대한 여러 값으로 알파벳순으로 첫 번째 숫자 (현재 로캘에 따라)가 선택됩니다. 즉, ORDER BY id, name의 값입니다. name이 모호한 경우 해당 행을 생략 할 수 있습니다.

id 당 하나 이상의 null이 아닌 값이 있으면 WHERE name IS NOT NULL을 생략 할 수 있습니다.