2015-05-11 33 views
10

tôi có bảng nhưXóa bản ghi trùng lặp khỏi bảng Postgresql mà không có khóa chính?

CREATE TABLE meta.fk_payment1 
(
    id serial NOT NULL, 
    settlement_ref_no character varying, 
    order_type character varying, 
    fulfilment_type character varying, 
    seller_sku character varying, 
    wsn character varying, 
    order_id character varying, 
    order_item_id bigint, 
    .... 
); 

tôi đang chèn dữ liệu từ file csv nơi tất cả các cột là như nhau thay vì cột id

Trong trường hợp khi tập tin csv tải lên nhiều hơn sau đó một thời gian dữ liệu sẽ được trùng lặp.

nhưng id sẽ không và id là khóa chính.

vì vậy tôi muốn xóa tất cả hàng trùng lặp mà không sử dụng khóa chính.

Tôi phải làm điều này trên một bảng

+3

Tạo bảng sao chép, hãy chèn vào bảng mới chọn khác với tệp cũ. – jarlh

+0

Tôi cần làm điều này trên một bảng –

+2

Tôi hơi bối rối về "id là khóa chính", nhưng "xóa ... mà không cần sử dụng khóa chính". Bạn có nghĩa là không có khóa chính trong csv, nhưng trong cơ sở dữ liệu có một? Nên chỉnh sửa câu hỏi để có một chút rõ ràng hơn về điều này. –

Trả lời

2

Sao chép dữ liệu riêng biệt vào bảng làm việc fk_payment1_copy. Cách đơn giản nhất để làm điều đó là sử dụng into

SELECT max(id),settlement_ref_no ... 
INTO fk_payment1_copy 
from fk_payment1 
GROUP BY settlement_ref_no ... 

xóa tất cả các hàng từ fk_payment1

delete from fk_payment1 

và sao chép dữ liệu từ fk_payment1_copy bảng để fk_payment1

insert into fk_payment1 
select id,settlement_ref_no ... 
from fk_payment1_copy 
+0

có thể thực hiện bằng cách sử dụng bảng đơn –

+0

@Shubhambatra Tôi không chắc chắn nếu có cách đơn giản nhất. Bạn không thể tạo bảng mới, phải không? – Parado

+0

Tôi có thể tạo nhưng trong tương lai nếu bất kỳ cột nào trở thành khóa ngoại thì không thể xóa từ fk_payment1. Là nó? –

1

Một chút không chắc chắn về chính phần quan trọng trong câu hỏi, nhưng trong mọi trường hợp, id không cần phải là khóa chính, nó chỉ cần là duy nhất. Vì nó nên được kể từ khi nó nối tiếp. Vì vậy, nếu nó có giá trị duy nhất, bạn có thể làm theo cách này:

DELETE FROM fk_payment1 f WHERE EXISTS 
    (SELECT * FROM fk_payment1 WHERE id<f.id 
    AND settlement_ref_no=f.settlement_ref_no 
    AND ...) 

Chỉ cần thêm tất cả các cột trong truy vấn chọn. Bằng cách này, tất cả các hàng có cùng giá trị (ngoại trừ id) và sau hàng này (được sắp xếp theo id) sẽ bị xóa.

(Ngoài ra, đặt tên một bảng với tiền tố fk_ làm cho nó trông giống như một khóa ngoại.)

+0

Tôi sử dụng tính năng này nhưng không cho kết quả chính xác. thiếu một số hàng. –

12

Bạn có thể làm như thế này ví dụ

DELETE FROM table_name 
    WHERE ctid NOT IN 
    (SELECT  MAX(dt.ctid) 
     FROM  table_name As dt 
     GROUP BY dt.*); 

chạy truy vấn này

DELETE FROM meta.fk_payment1 
    WHERE ctid NOT IN 
    (SELECT  MAX(dt.ctid) 
     FROM  meta.fk_payment1 As dt 
     GROUP BY dt.*); 
1

nếu bảng không phải là rất lớn, bạn có thể làm:

-- create temporary table and select distinct into it. 
CREATE TEMP TABLE tmp_table AS 
SELECT DISTINCT column_1, column_2 
FROM original_table ORDER BY column_1, column_2; 

-- clear the original table 
TRUNCATE original_table; 

-- copy data back in again 
INSERT INTO original_table(column_1, column_2) 
SELECT * FROM tmp_table ORDER BY column_1, column_2; 

-- clean up 
DROP TABLE tmp_table 
  • cho các bảng lớn hơn loại bỏ các lệnh TEMP từ việc tạo ra tmp_table
  • giải pháp này có trong tiện dụng khi làm việc với JPA (Hibernate) được tạo ra @ElementCollection được tạo mà không có khóa chính.
0

Vì vậy, có một cách khéo léo ngay trong PG wiki. https://wiki.postgresql.org/wiki/Deleting_duplicates

Truy vấn này thực hiện điều đó cho tất cả các hàng tablename có cùng cột1, cột2 và cột3.

DELETE FROM tablename 
WHERE id IN (SELECT id 
       FROM (SELECT id, 
          ROW_NUMBER() OVER (partition BY column1, column2, column3 ORDER BY id) AS rnum 
        FROM tablename) t 
       WHERE t.rnum > 1); 

Tôi đã thử nghiệm điều này trên các hàng 600 nghìn vạch, dẫn đến 200 nghìn hàng duy nhất. Giải pháp sử dụng nhóm và NOT IN mất 3h +, điều này sẽ giống như 3s.

Các vấn đề liên quan