PostgreSQL में डुप्लिकेट रिकॉर्ड कैसे खोजें


189

मेरे पास एक PostgreSQL डेटाबेस टेबल है, जिसे "user_links" कहा जाता है, जो वर्तमान में निम्नलिखित डुप्लिकेट फ़ील्ड की अनुमति देता है:

year, user_id, sid, cid

अद्वितीय बाधा वर्तमान में पहले क्षेत्र "आईडी" कहा जाता है, लेकिन अब मैं सुनिश्चित करने के लिए एक बाधा को जोड़ने के लिए देख रहा हूँ है year, user_id, sidऔर cidसभी अद्वितीय हैं, लेकिन मैं बाधा लागू नहीं कर सकते क्योंकि डुप्लिकेट मानों पहले से ही मौजूद है जो इस बाधा उल्लंघन करते हैं।

क्या सभी डुप्लिकेट खोजने का एक तरीका है?


जवाबों:


334

मूल विचार गिनती एकत्रीकरण के साथ एक नेस्टेड क्वेरी का उपयोग किया जाएगा:

select * from yourTable ou
where (select count(*) from yourTable inr
where inr.sid = ou.sid) > 1

आप खोज को संकीर्ण करने के लिए आंतरिक क्वेरी में जहां खंड को समायोजित कर सकते हैं।


टिप्पणियों में उल्लेखित के लिए एक और अच्छा समाधान है, (लेकिन हर कोई उन्हें नहीं पढ़ता है):

select Column1, Column2, count(*)
from yourTable
group by Column1, Column2
HAVING count(*) > 1

या कम:

SELECT (yourTable.*)::text, count(*)
FROM yourTable
GROUP BY yourTable.*
HAVING count(*) > 1

65
आप select co1, col2, count(*) from tbl group by col1, col2 HAVING count(*)>1
HAVING का

1
धन्यवाद @alexkovelsky का कथन मेरे लिए संशोधित करना आसान था और जल्दी भाग गया। मैं उच्च दृश्यता के लिए इसके साथ एक उत्तर देना चाहूंगा।
वेसेंटो

इन विकल्पों ने मेरे लिए काम किया, अन्य लोगों ने परिणामों को समूहित किया, और इन विकल्पों ने मुझे केवल रिकॉर्ड किए गए डुप्लिकेट के बजाय सभी डुप्लिकेट किए गए रिकॉर्ड दिए, धन्यवाद!
रोमियो ३३

1
मेरे पास आपका जवाब है कि यह थोड़ा धीमा है। एक तालिका 10k पंक्तियों पर * 18 कॉलम, क्वेरी 8 सेकंड
aydow

1
ठीक है वहाँ भाई जाम। हां, यह तो हैरत की बात है। धन्यवाद। 💯
डीपीएस

90

यहाँ "स्मार्ट पोस्ट समाधान के साथ डुप्लिकेट पंक्तियाँ खोजें " से :

select * from (
  SELECT id,
  ROW_NUMBER() OVER(PARTITION BY column1, column2 ORDER BY id asc) AS Row
  FROM tbl
) dups
where 
dups.Row > 1

11
यह उपवास है! सेकंड के एक अंश में लाखों पंक्तियों पर काम किया। अन्य उत्तर बस वहीं लटके मिले ...
dmvianna

5
जैसा कि मैंने देखा है, यह क्वेरी किसी समूह में सभी पंक्तियों पर विचार नहीं करती है। यह केवल किसी चीज़ के लिए डुप्लिकेट दिखाता है, डुप्लिकेट का हिस्सा
रोन्नम

9
@vladimir Filipchenko सभी लाइनों के साथ इसे करने के लिए, एलेक्सकोवेल्स्की समाधान के लिए एक स्तर जोड़ें:SELECT * FROM ( SELECT *, LEAD(row,1) OVER () AS nextrow FROM ( SELECT *, ROW_NUMBER() OVER(w) AS row FROM tbl WINDOW w AS (PARTITION BY col1, col2 ORDER BY col3) ) x ) y WHERE row > 1 OR nextrow > 1;
Le Droid

3
@VladimirFilipchenko बस के ROW_NUMBER()साथ बदलें COUNT(*), और rows between unbounded preceding and unbounded followingबाद में जोड़ेंORDER BY id asc
एलेक्सकोवेल्स्की

2
मैंने पाया अन्य समाधानों की तुलना में बहुत बेहतर है। भी साथ ड्यूप्स को हटाने के लिए अच्छी तरह से समान रूप से काम करता है DELETE ...USINGऔर कुछ मामूली समायोजन
ब्रैंडन

6

आप उसी फ़ील्ड में उसी तालिका में शामिल हो सकते हैं जिसे डुप्लिकेट किया जाएगा और फिर आईडी फ़ील्ड पर एंटी-जॉइन किया जाएगा। पहली तालिका उपनाम (tn1) से आईडी फ़ील्ड का चयन करें और फिर दूसरी तालिका आईडी के आईडी फ़ील्ड पर array_agg फ़ंक्शन का उपयोग करें। अंत में, array_agg फ़ंक्शन को ठीक से काम करने के लिए, आप परिणाम को tn1.id फ़ील्ड द्वारा समूहित करेंगे। यह एक परिणाम सेट का उत्पादन करेगा जिसमें एक रिकॉर्ड की आईडी और सभी आईडी की एक सरणी होती है जो जुड़ने की स्थिति में फिट होती है।

select tn1.id,
       array_agg(tn2.id) as duplicate_entries, 
from table_name tn1 join table_name tn2 on 
    tn1.year = tn2.year 
    and tn1.sid = tn2.sid 
    and tn1.user_id = tn2.user_id 
    and tn1.cid = tn2.cid
    and tn1.id <> tn2.id
group by tn1.id;

जाहिर है, आईडी जो एक आईडी के लिए डुप्लिकेट_एंट्रीज सरणी में होगी, परिणाम सेट में उनकी अपनी प्रविष्टियां भी होंगी। आपको इस परिणाम का उपयोग यह तय करने के लिए करना होगा कि आप किस आईडी से 'सत्य' का स्रोत बनना चाहते हैं। एक रिकॉर्ड जिसे हटाया नहीं जाना चाहिए। शायद आप ऐसा कुछ कर सकते हैं:

with dupe_set as (
select tn1.id,
       array_agg(tn2.id) as duplicate_entries, 
from table_name tn1 join table_name tn2 on 
    tn1.year = tn2.year 
    and tn1.sid = tn2.sid 
    and tn1.user_id = tn2.user_id 
    and tn1.cid = tn2.cid
    and tn1.id <> tn2.id
group by tn1.id
order by tn1.id asc)
select ds.id from dupe_set ds where not exists 
 (select de from unnest(ds.duplicate_entries) as de where de < ds.id)

सबसे कम संख्या वाली आईडी का चयन करता है जिसमें डुप्लिकेट है (मान लिया गया है कि आईडी पीके बढ़ा रहा है)। ये वह आईडी होगी जिसे आप अपने आसपास रखेंगे।


3

इसे आसान बनाने के लिए मैं मानता हूं कि आप केवल कॉलम वर्ष के लिए एक अद्वितीय बाधा लागू करना चाहते हैं और प्राथमिक कुंजी आईडी नाम का एक कॉलम है।

डुप्लिकेट मान ढूँढने के लिए आपको चलना चाहिए,

SELECT year, COUNT(id)
FROM YOUR_TABLE
GROUP BY year
HAVING COUNT(id) > 1
ORDER BY COUNT(id);

ऊपर दिए गए sql स्टेटमेंट का उपयोग करने से आपको एक तालिका मिलती है जिसमें आपकी तालिका में सभी डुप्लिकेट वर्ष होते हैं। आदेश में नवीनतम डुप्लिकेट प्रविष्टि के छोड़कर सभी डुप्लिकेट हटाने के लिए आप एसक्यूएल बयान से ऊपर का उपयोग करना चाहिए।

DELETE
FROM YOUR_TABLE A USING YOUR_TABLE_AGAIN B
WHERE A.year=B.year AND A.id<B.id;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.