डुप्लिकेट प्रविष्टियों को कैसे हटाएं?


92

मुझे एक मौजूदा तालिका में एक अद्वितीय बाधा जोड़ना है। यह ठीक है सिवाय इसके कि तालिका में लाखों पंक्तियाँ पहले से हैं, और कई पंक्तियाँ अद्वितीय बाधा का उल्लंघन करती हैं जिन्हें मुझे जोड़ने की आवश्यकता है।

आक्रामक पंक्तियों को हटाने के लिए सबसे तेज़ तरीका क्या है? मेरे पास एक एसक्यूएल स्टेटमेंट है जो डुप्लिकेट ढूंढता है और उन्हें हटा देता है, लेकिन इसे चलाने के लिए हमेशा के लिए ले जा रहा है। क्या इस समस्या को हल करने का एक और तरीका है? हो सकता है कि टेबल का बैकअप लेने के बाद, फिर बाधा डालने के बाद बहाल किया जाए?

जवाबों:


101

उदाहरण के लिए आप कर सकते हैं:

CREATE TABLE tmp ...
INSERT INTO tmp SELECT DISTINCT * FROM t;
DROP TABLE t;
ALTER TABLE tmp RENAME TO t;

2
क्या आप इसे स्तंभों के समूह के लिए विशिष्ट बना सकते हैं। हो सकता है "SELECT DISTINCT (ta, tb, tc), * FROM t"?
gjrwebber


36
टाइप करने में आसान CREATE TABLE tmp AS SELECT ...;:। फिर आपको यह पता लगाने की जरूरत नहीं है कि लेआउट क्या tmpहै। :)
रैंडल श्वार्ट्ज

9
यह उत्तर वास्तव में कई कारणों से बहुत अच्छा नहीं है। @ रैंडल ने एक नाम दिया। ज्यादातर मामलों में, विशेषकर यदि आपके पास अनुक्रमणिका, बाधाओं, विचारों आदि जैसी वस्तुओं पर निर्भर करता है, तो बेहतर तरीका यह है कि वास्तविक TEMPORARY TABLE का उपयोग किया जाए , मूल को पुन: लिखें और डेटा को फिर से डालें।
एरविन ब्रान्डसेट्टर

7
आप अनुक्रमित के बारे में सही हैं। ड्रोपिंग और मनोरंजन बहुत तेज है। लेकिन अन्य निर्भर वस्तुएं टेबल को पूरी तरह से तोड़ने या रोकने से रोकेंगी - जो कि ओपी को कॉपी बनाने के बाद पता चलेगा - "सबसे तेज़ दृष्टिकोण" के लिए। फिर भी, आप डाउनवोट के बारे में सही हैं। यह निराधार है, क्योंकि यह एक बुरा जवाब नहीं है। यह सिर्फ इतना अच्छा नहीं है। आप अनुक्रमणिका या निर्भर वस्तुओं के बारे में कुछ संकेत जोड़ सकते थे या मैनुअल की एक कड़ी जैसा कि आपने टिप्पणी या किसी भी तरह के स्पष्टीकरण में किया था। मुझे लगता है कि मैं निराश हूं कि लोग कैसे वोट देते हैं। उतार को हटा दिया।
इरविन ब्रान्डेसटेटर

173

इनमें से कुछ दृष्टिकोण थोड़ा जटिल लगते हैं, और मैं आमतौर पर ऐसा करता हूं:

तालिका को देखते हुए table, इसे अधिकतम फ़ील्ड 3 के साथ पंक्ति को रखते हुए (फ़ील्ड 1, फ़ील्ड 2) पर अद्वितीय बनाना चाहते हैं:

DELETE FROM table USING table alias 
  WHERE table.field1 = alias.field1 AND table.field2 = alias.field2 AND
    table.max_field < alias.max_field

उदाहरण के लिए, मेरे पास एक तालिका है, user_accountsऔर मैं ईमेल पर एक अद्वितीय बाधा जोड़ना चाहता हूं, लेकिन मेरे पास कुछ डुप्लिकेट हैं। यह भी कहें कि मैं हाल ही में बनाई गई एक (अधिकतम आईडी डुप्लिकेट के बीच) रखना चाहता हूं।

DELETE FROM user_accounts USING user_accounts ua2
  WHERE user_accounts.email = ua2.email AND user_account.id < ua2.id;
  • नोट - USINGयह मानक SQL नहीं है, यह एक PostgreSQL एक्सटेंशन है (लेकिन बहुत उपयोगी है), लेकिन मूल प्रश्न में विशेष रूप से PostgreSQL का उल्लेख है।

4
पोस्टग्रेज पर यह दूसरा तरीका बहुत तेज है! धन्यवाद।
एरिक बोमन - अमूर्तो -

5
@ क्या आप बेहतर तरीके से समझा सकते हैं कि USINGपोस्टग्रैसक्ल में क्या होता है?
फोपा लियोन कॉन्स्टैंटिन

3
यह अब तक का सबसे अच्छा जवाब है। यहां तक ​​कि अगर आपके पास आईडी तुलना के लिए उपयोग करने के लिए आपकी तालिका में एक सीरियल कॉलम नहीं है, तो यह इस सरल दृष्टिकोण का उपयोग करने के लिए अस्थायी रूप से जोड़ने के लिए इसके लायक है।
शेन

2
मैंने अभी जाँच की। जवाब है हां, यह होगा। कम-से-कम (<) का उपयोग करना आपको केवल अधिकतम आईडी के साथ छोड़ देता है, जबकि अधिक से अधिक (>) आपको केवल न्यूनतम आईडी के साथ छोड़ देता है, बाकी को हटा देता है।
एंड्रे सी। एंडरसन

1
@Shane एक का उपयोग कर सकते हैं: WHERE table1.ctid<table2.ctid- धारावाहिक स्तंभ जोड़ने की कोई जरूरत नहीं
एलेक्सकोवेल्स्की

25

एक नई तालिका बनाने के बजाय, आप इसे रौंदने के बाद एक ही तालिका में अद्वितीय पंक्तियों को फिर से सम्मिलित कर सकते हैं। यह सब एक लेन-देन में करें । वैकल्पिक रूप से, आप लेनदेन के अंत में अस्थायी तालिका को स्वचालित रूप से छोड़ सकते हैं ON COMMIT DROP। निचे देखो।

यह दृष्टिकोण केवल उपयोगी है जहां मेज पर सभी से हटाने के लिए बहुत सारी पंक्तियाँ हैं। बस कुछ डुप्लिकेट के लिए, एक सादे का उपयोग करें DELETE

आपने लाखों पंक्तियों का उल्लेख किया। ऑपरेशन को तेज़ करने के लिए आप सत्र के लिए पर्याप्त अस्थायी बफ़र्स आवंटित करना चाहते हैं । आपके मौजूदा सत्र में किसी भी अस्थायी बफर का उपयोग करने से पहले सेटिंग को समायोजित करना होगा । अपनी तालिका का आकार ज्ञात करें:

SELECT pg_size_pretty(pg_relation_size('tbl'));

temp_buffersतदनुसार सेट करें । इन-मेमोरी प्रतिनिधित्व को थोड़ा अधिक रैम की आवश्यकता के कारण उदारतापूर्वक गोल करें।

SET temp_buffers = 200MB;    -- example value

BEGIN;

-- CREATE TEMPORARY TABLE t_tmp ON COMMIT DROP AS -- drop temp table at commit
CREATE TEMPORARY TABLE t_tmp AS  -- retain temp table after commit
SELECT DISTINCT * FROM tbl;  -- DISTINCT folds duplicates

TRUNCATE tbl;

INSERT INTO tbl
SELECT * FROM t_tmp;
-- ORDER BY id; -- optionally "cluster" data while being at it.

COMMIT;

यदि ऑब्जेक्ट मौजूद हैं, तो यह विधि एक नई तालिका बनाने के लिए बेहतर हो सकती है। तालिका को संदर्भित करने वाले दृश्य, अनुक्रमणिका, विदेशी कुंजियाँ या अन्य वस्तुएँ। TRUNCATEआप वैसे भी एक साफ स्लेट के साथ शुरू करते हैं (पृष्ठभूमि में नई फ़ाइल) और बड़ी तालिकाओं की तुलना में बहुत तेज है DELETE FROM tbl( DELETEवास्तव में बड़ी तालिकाओं के साथ तेज हो सकती है)।

बड़ी तालिकाओं के लिए, अनुक्रमित और विदेशी कुंजियों को छोड़ना, तालिका को फिर से भरना और इन वस्तुओं को फिर से बनाना नियमित रूप से तेज़ है। जहाँ तक fk बाधाओं का संबंध है, तो आपको निश्चित होना चाहिए कि नया डेटा निश्चित रूप से मान्य है या आप fk बनाने के प्रयास पर अपवाद में चलेंगे।

ध्यान दें कि TRUNCATEकी तुलना में अधिक आक्रामक लॉकिंग की आवश्यकता होती है DELETE। यह भारी, समवर्ती भार वाली तालिकाओं के लिए एक मुद्दा हो सकता है।

तो TRUNCATEएक विकल्प या के लिए आम तौर पर नहीं है छोटे मध्यम तालिकाओं के लिए वहाँ के साथ एक समान तकनीक है एक डेटा में सुधार करने वाले CTE (Postgres 9.1 +):

WITH del AS (DELETE FROM tbl RETURNING *)
INSERT INTO tbl
SELECT DISTINCT * FROM del;
-- ORDER BY id; -- optionally "cluster" data while being at it.

बड़ी तालिकाओं के लिए धीमी, क्योंकि TRUNCATEवहां तेजी है। लेकिन छोटी तालिकाओं के लिए तेज (और सरल!) हो सकता है।

यदि आपके पास कोई वस्तु नहीं है, तो आप एक नई तालिका बना सकते हैं और पुरानी को हटा सकते हैं, लेकिन आप इस सार्वभौमिक दृष्टिकोण पर शायद ही कुछ हासिल कर सकते हैं।

बहुत बड़ी तालिकाओं के लिए जो उपलब्ध रैम में फिट नहीं होंगे , एक नई तालिका बनाने से काफी तेज हो जाएगा। आपको संभावित वस्तुओं / ओवरहेड पर निर्भर वस्तुओं के साथ इसका वजन करना होगा।


2
मैंने इस दृष्टिकोण का भी इस्तेमाल किया। हालाँकि, यह व्यक्तिगत हो सकता है, लेकिन मेरी अस्थायी तालिका हटा दी गई थी, और ट्रंकट के बाद उपलब्ध नहीं थी ... उन चरणों को करने के लिए सावधान रहें यदि अस्थायी तालिका सफलतापूर्वक बनाई गई थी और उपलब्ध है।
क्लेश

@xlash: आप यह सुनिश्चित करने के लिए अस्तित्व की जांच कर सकते हैं, या तो अस्थायी तालिका के लिए एक अलग नाम का उपयोग करें या अस्तित्व में किसी का पुन: उपयोग करें .. मैंने अपने उत्तर में थोड़ा सा जोड़ा।
इरविन ब्रान्डेसटेटर 22

चेतावनी: सावधान रहें +1 से @xlash - मुझे अपने डेटा को फिर से आयात करना होगा क्योंकि अस्थायी तालिका के बाद गैर-मौजूद था TRUNCATE। जैसा कि इरविन ने कहा, यह सुनिश्चित करना सुनिश्चित करें कि यह आपकी तालिका को छोटा करने से पहले मौजूद है। @ Codebykat का उत्तर देखें
जॉर्डन आर्सेनो

1
@JordanArseno: मैंने बिना किसी संस्करण के स्विच किया ON COMMIT DROP, ताकि वे लोग जो उस हिस्से को याद करते हैं जहां मैंने "एक लेनदेन में" लिखा है डेटा खोना नहीं है। और मैंने "एक लेनदेन" को स्पष्ट करने के लिए BEGIN / COMMIT को जोड़ा।
इरविन ब्रान्डेसटेटर

1
14 मिलियन रिकॉर्ड के साथ टेबल पर 3 घंटे से अधिक समय तक उपयोग करने के साथ समाधान। Temp_buffers के साथ इस समाधान में 13 मिनट लगे। धन्यवाद।
castt

20

आप oid या ctid का उपयोग कर सकते हैं, जो आम तौर पर तालिका में "गैर-दृश्यमान" कॉलम है:

DELETE FROM table
 WHERE ctid NOT IN
  (SELECT MAX(s.ctid)
    FROM table s
    GROUP BY s.column_has_be_distinct);

4
को हटाने के लिए जगह में , NOT EXISTSकाफी तेज किया जाना चाहिए : DELETE FROM tbl t WHERE EXISTS (SELECT 1 FROM tbl t1 WHERE t1.dist_col = t.dist_col AND t1.ctid > t.ctid)- या एक उत्तरजीवी लेने के लिए करने के लिए छँटाई के लिए किसी भी अन्य स्तंभ या स्तंभों के सेट का उपयोग करें।
इरविन ब्रान्डेसटेटर

@ErwinBrandstetter, क्या आपके द्वारा उपयोग की जाने वाली क्वेरी है NOT EXISTS?
जॉन

1
@ जॉन: यह EXISTSयहाँ होना चाहिए । इसे इस तरह पढ़ें: "उन सभी पंक्तियों को हटा दें जहां कोई अन्य पंक्ति समान मान के साथ मौजूद है dist_colलेकिन एक बड़ी ctid"। डुप्स के प्रति समूह का एकमात्र उत्तरजीवी सबसे बड़ा होगा ctid
इरविन ब्रान्डेसटेटर

सबसे आसान समाधान यदि आपके पास केवल कुछ डुप्लिकेट पंक्तियाँ हैं। LIMITयदि आप डुप्लिकेट की संख्या जानते हैं तो इसका उपयोग किया जा सकता है ।
स्किप्पी ले ग्रांड गौरौ सेप

19

इस समस्या के लिए PostgreSQL विंडो फ़ंक्शन आसान है।

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

डुप्लिकेट हटाएं देखें ।


और "आईडी" के बजाय "ctid" का उपयोग करते हुए, यह वास्तव में पूरी तरह से डुप्लिकेट पंक्तियों के लिए काम करता है।
bradw2k

महान समाधान। मुझे एक अरब रिकॉर्ड वाली तालिका के लिए ऐसा करना था। मैंने WHERE को इनर सेलेक्ट में जोड़ा कि इसे चंक्स में करें।
Jan

7

से एक पुराने postgresql.org मेलिंग सूची :

create table test ( a text, b text );

अद्वितीय मूल्य

insert into test values ( 'x', 'y');
insert into test values ( 'x', 'x');
insert into test values ( 'y', 'y' );
insert into test values ( 'y', 'x' );

मूल्यों को डुप्लिकेट करें

insert into test values ( 'x', 'y');
insert into test values ( 'x', 'x');
insert into test values ( 'y', 'y' );
insert into test values ( 'y', 'x' );

एक और डबल डुप्लिकेट

insert into test values ( 'x', 'y');

select oid, a, b from test;

डुप्लिकेट पंक्तियों का चयन करें

select o.oid, o.a, o.b from test o
    where exists ( select 'x'
                   from test i
                   where     i.a = o.a
                         and i.b = o.b
                         and i.oid < o.oid
                 );

डुप्लिकेट पंक्तियों को हटाएँ

नोट: PostgreSQL fromएक डिलीट के क्लॉज में बताए गए टेबल पर उपनाम का समर्थन नहीं करता है ।

delete from test
    where exists ( select 'x'
                   from test i
                   where     i.a = test.a
                         and i.b = test.b
                         and i.oid < test.oid
             );

आपकी व्याख्या बहुत ही स्मार्ट है, लेकिन आप एक बिंदु को याद कर रहे हैं, तालिका बनाने में ओड निर्दिष्ट करें और उसके बाद ही ओड को अन्य त्रुटि संदेश प्रदर्शन तक पहुंचें
कलानिधि

@Kalanidhi उत्तर में सुधार के बारे में आपकी टिप्पणी के लिए धन्यवाद, मैं इस बिंदु पर विचार करूंगा।
भाविक अंबानी

यह वास्तव में postgresql.org/message-id/…
मार्टिन एफ

आप सिस्टम कॉलम 'ctid' का उपयोग कर सकते हैं यदि 'oid' आपको कोई त्रुटि देता है।
sul4bh

7

डुप्लिकेट हटाने के लिए सामान्यीकृत क्वेरी:

DELETE FROM table_name
WHERE ctid NOT IN (
  SELECT max(ctid) FROM table_name
  GROUP BY column1, [column 2, ...]
);

स्तंभ ctidहर तालिका के लिए उपलब्ध एक विशेष स्तंभ है लेकिन विशेष रूप से उल्लेख किए जाने तक दिखाई नहीं देता है। ctidस्तंभ मान किसी तालिका में प्रत्येक पंक्ति के लिए अद्वितीय माना जाता है।


एकमात्र सार्वभौमिक उत्तर! स्व / कार्टेशियन जॉइन के बिना काम करता है। वर्थ जोड़ना हालांकि यह कि GROUP BYक्लॉज को सही ढंग से निर्दिष्ट करने के लिए आवश्यक है - यह 'विशिष्टता मानदंड' होना चाहिए जिसका अब उल्लंघन किया गया है या यदि आप डुप्लिकेट का पता लगाना चाहते हैं। यदि निर्दिष्ट गलत है तो यह सही तरीके से काम नहीं करेगा
msciwoj

4

मैंने अभी-अभी Erwin Brandstetter के उत्तर का उपयोग जॉइन टेबल में डुप्लिकेट को हटाने के लिए सफलतापूर्वक किया था (एक टेबल की अपनी प्राथमिक आईडी की कमी थी), लेकिन पाया कि वहाँ एक महत्वपूर्ण चेतावनी है।

शामिल करने का ON COMMIT DROPमतलब है कि लेनदेन के अंत में अस्थायी तालिका गिरा दी जाएगी। मेरे लिए, इसका मतलब यह था कि अस्थायी तालिका अब उस समय तक उपलब्ध नहीं थी जब मैं इसे सम्मिलित करता था!

मैंने बस किया CREATE TEMPORARY TABLE t_tmp AS SELECT DISTINCT * FROM tbl;और सब कुछ ठीक रहा।

अस्थायी तालिका सत्र के अंत में गिरा दी जाती है।


3

यह फ़ंक्शन इंडेक्स को हटाए बिना डुप्लिकेट को हटाता है और किसी भी तालिका में करता है।

उपयोग: select remove_duplicates('mytable');

---
--- remove_duplicates (tablename) एक तालिका से डुप्लिकेट रिकॉर्ड को निकालता है (सेट से अनन्य सेट में परिवर्तित करें)
---
क्रिएट या रिप्लाई फंक्शन रिमूव_डुप्लिकेट्स (टेक्स्ट) RETURNS शून्य के रूप में $ $
घोषित
  $ 1 के लिए tablename ALIAS;
शुरू
  EXECUTE 'CREATE TEMPORARY TABLE _DISTINCT_' || तबला || 'AS (Select DISTINCT * FROM' || tablename || ');';
  EXECUTE 'DELETE FROM' || तबला || ';';
  EXECUTE 'INSERT INTO' || तबला || '(SELECT * FROM _DISTINCT_' || tablename || ')?';
  EXECUTE 'DROP TABLE _DISTINCT_' || तबला || ';';
  वापसी;
समाप्त;
$ $ भाषा प्लेगसक्कल;

3
DELETE FROM table
  WHERE something NOT IN
    (SELECT     MAX(s.something)
      FROM      table As s
      GROUP BY  s.this_thing, s.that_thing);

यही मैं वर्तमान में कर रहा हूं, लेकिन इसे चलाने में बहुत लंबा समय लग रहा है।
gjrwebber 3

1
क्या यह विफल नहीं होगा यदि तालिका में कई पंक्तियों का स्तंभ में समान मूल्य है?
श्रीधर

3

यदि आपके पास केवल एक या कुछ डुप्लिकेट प्रविष्टियाँ हैं, और वे वास्तव में डुप्लिकेट हैं (अर्थात, वे दो बार दिखाई देते हैं), आप "छिपे हुए" ctidकॉलम का उपयोग कर सकते हैं , जैसा कि ऊपर प्रस्तावित है, साथ में LIMIT:

DELETE FROM mytable WHERE ctid=(SELECT ctid FROM mytable WHERE […] LIMIT 1);

यह केवल पहले चयनित पंक्तियों को हटा देगा।


मुझे पता है कि यह ओपी के मुद्दे को संबोधित नहीं करता है, जिन्होंने लाखों पंक्तियों में कई नकल की है, लेकिन यह वैसे भी मददगार हो सकता है।
स्किप्पी ले ग्रैंड गौरौ

इसे प्रत्येक डुप्लिकेट पंक्ति के लिए एक बार चलाना होगा। शेकवी के उत्तर को केवल एक बार चलाने की आवश्यकता है।
bradw2k

3

सबसे पहले, आपको यह तय करने की आवश्यकता है कि आप अपने "डुप्लिकेट" में से किस पर रखेंगे। यदि सभी कॉलम समान हैं, ठीक है, तो आप उनमें से किसी को भी हटा सकते हैं ... लेकिन शायद आप केवल सबसे हाल ही में, या कुछ अन्य मानदंड रखना चाहते हैं?

सबसे तेज़ तरीका ऊपर दिए गए प्रश्न के आपके उत्तर पर निर्भर करता है, और टेबल पर डुप्लिकेट के% पर भी। यदि आप अपनी 50% पंक्तियों को फेंक देते हैं, तो आप बेहतर कर रहे हैं CREATE TABLE ... AS SELECT DISTINCT ... FROM ... ;, और यदि आप 1% पंक्तियों को हटाते हैं , तो DELETE का उपयोग करना बेहतर है।

इस तरह के रखरखाव के संचालन के लिए, यह आम तौर पर work_memआपके रैम का एक अच्छा हिस्सा सेट करने के लिए अच्छा है: EXPLAIN को चलाएं, सॉर्ट / हैश की संख्या की जांच करें, और अपने RAM / 2 / N के लिए work_mem सेट करें। RAM का बहुत उपयोग करें; यह गति के लिए अच्छा है। जब तक आप केवल एक समवर्ती कनेक्शन है ...


1

मैं PostgreSQL 8.4 के साथ काम कर रहा हूं। जब मैंने प्रस्तावित कोड चलाया, तो मैंने पाया कि यह वास्तव में डुप्लिकेट को हटा नहीं रहा था। कुछ परीक्षणों को चलाने में, मैंने पाया कि "DISTINCT ON (डुप्लिकेट_ कोलम्ब_नाम)" और "ओआरडीईआर बाय डुप्लिकेट_कॉम्बिन_नाम" को जोड़कर चाल चली। मैं कोई SQL गुरु नहीं हूँ, मुझे यह पोस्टग्रेसीक्यूएल 8.4 चयन में मिला ... DISTINCT doc।

CREATE OR REPLACE FUNCTION remove_duplicates(text, text) RETURNS void AS $$
DECLARE
  tablename ALIAS FOR $1;
  duplicate_column ALIAS FOR $2;
BEGIN
  EXECUTE 'CREATE TEMPORARY TABLE _DISTINCT_' || tablename || ' AS (SELECT DISTINCT ON (' || duplicate_column || ') * FROM ' || tablename || ' ORDER BY ' || duplicate_column || ' ASC);';
  EXECUTE 'DELETE FROM ' || tablename || ';';
  EXECUTE 'INSERT INTO ' || tablename || ' (SELECT * FROM _DISTINCT_' || tablename || ');';
  EXECUTE 'DROP TABLE _DISTINCT_' || tablename || ';';
  RETURN;
END;
$$ LANGUAGE plpgsql;

1

यह बहुत अच्छी तरह से काम करता है और बहुत जल्दी है:

CREATE INDEX otherTable_idx ON otherTable( colName );
CREATE TABLE newTable AS select DISTINCT ON (colName) col1,colName,col2 FROM otherTable;

1
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);

कॉलम (ओं) द्वारा डुप्लिकेट हटाएं और सबसे कम आईडी के साथ पंक्ति रखें। पैटर्न पोस्टग्रिज विकि से लिया गया है

CTE के उपयोग से आप इसके माध्यम से उपरोक्त का अधिक पठनीय संस्करण प्राप्त कर सकते हैं

WITH duplicate_ids as (
    SELECT id, rnum 
    FROM num_of_rows
    WHERE rnum > 1
),
num_of_rows as (
    SELECT id, 
        ROW_NUMBER() over (partition BY column1, 
                                        column2, 
                                        column3 ORDER BY id) AS rnum
        FROM tablename
)
DELETE FROM tablename 
WHERE id IN (SELECT id from duplicate_ids)

1
CREATE TABLE test (col text);
INSERT INTO test VALUES
 ('1'),
 ('2'), ('2'),
 ('3'),
 ('4'), ('4'),
 ('5'),
 ('6'), ('6');
DELETE FROM test
 WHERE ctid in (
   SELECT t.ctid FROM (
     SELECT row_number() over (
               partition BY col
               ORDER BY col
               ) AS rnum,
            ctid FROM test
       ORDER BY col
     ) t
    WHERE t.rnum >1);

मैंने इसका परीक्षण किया, और इसने काम किया; मैंने इसे पठनीयता के लिए स्वरूपित किया। यह काफी परिष्कृत दिखता है, लेकिन यह कुछ स्पष्टीकरण का उपयोग कर सकता है। कोई व्यक्ति अपने स्वयं के उपयोग के मामले में इस उदाहरण को कैसे बदलेगा?
टोबियास
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.