2012-01-01 204 views
1

我必須從沒有主鍵或唯一約束的表中清除記錄。從沒有唯一列的表中刪除部分重複項

表定義:

create table person(
    name text, 
    staff_id integer, 
    work_code text, 
    location 
); 

不出所料,它含有大量的重複和部分重複的。 將記錄轉換爲唯一集合的最佳方式是什麼?我不必關心除名稱和職員以外的其他專欄

+0

你稱之爲「部分重複」? – fge 2012-01-01 19:17:29

+0

@ work_code和location_fge變體,我只需要保留name和staff_id – 2012-01-01 19:18:47

+0

你真的關心哪些值會得到最終結果嗎? – fge 2012-01-01 19:19:34

回答

4

正如你

不必在意除了名字等欄目和staff_id

這可能是你的程序來清理表:

1 )創建一個臨時表獨特行:

CREATE TEMP TABLE p_tmp AS 
SELECT DISTINCT ON (name, staff_id) 
     name, staff_id, work_code, location 
FROM person 
ORDER BY name, staff_id, work_code, location; 

我隨意選擇「第一行每(name, staff_id) - 最小work_code和匹配location

2)空表:

TRUNCATE person; 

3)重新插入獨特的元組:

INSERT INTO person SELECT * FROM p_tmp; 

確保,受騙者不悄悄潛回裏添加一個代理主鍵:

ALTER TABLE person ADD COLUMN person_id serial PRIMARY KEY; 
ALTER TABLE person ADD UNIQUE (name, staff_id); 

或者只需添加一個多列主鍵:

ALTER TABLE person ADD PRIMARY KEY (name, staff_id); 

臨時表將在會話結束時自動丟棄。

當然,所有這一切最好在一個transaction內完成,所以在不太可能出現半途遇到問題的情況下不會丟失任何東西。有些客戶端會自動執行一次執行的一批SQL語句。

+0

當然'max'比'min'更好;使空值最不可能被選中。 – Ben 2012-01-01 20:55:04

+0

@Ben:max()和min()都不會在**任何**值上選擇NULL。 – 2012-01-01 21:05:20

+0

@ErwinBrandstetter謝謝你,它很好地工作 – 2012-01-02 04:47:19

0

也許這樣?

select t.name, t.staff_id, t.work_code, t.location 
from (
    select name, staff_id, work_code, location, count(*) nr 
    from person 
    group by name, staff_id, work_code, location 
) t 
where t.nr > 1; 
+0

我很抱歉,我的意思是我需要擺脫部分重複行,但保留與所有其他值的1唯一行以及。我嘗試不同,但它仍然返回所有行 – 2012-01-01 19:27:27

+0

請參閱後編輯,做它回答您的需求? – fge 2012-01-01 19:33:45

+0

它抱怨說我需要將所有t。*列包含在group by子句中。當我這樣做時,它不返回任何行。我測試了子查詢,並且「nr」列從不包含大於1的值。 – 2012-01-01 19:53:10