MySQL में डुप्लिकेट रिकॉर्ड ढूंढें


650

मैं एक MySQL डाटाबेस में डुप्लिकेट रिकॉर्ड को बाहर निकालना चाहता हूं। इसके साथ किया जा सकता है:

SELECT address, count(id) as cnt FROM list
GROUP BY address HAVING cnt > 1

जिसके परिणामस्वरूप:

100 MAIN ST    2

मैं इसे खींचना चाहूंगा ताकि यह प्रत्येक पंक्ति को दिखाए जो एक डुप्लिकेट है। कुछ इस तरह:

JIM    JONES    100 MAIN ST
JOHN   SMITH    100 MAIN ST

यह कैसे किया जा सकता है पर कोई विचार? मैं पहले एक फिर कोड में दूसरी क्वेरी के साथ डुप्लिकेट को देखने से बचने की कोशिश कर रहा हूं।

जवाबों:


684

कुंजी इस क्वेरी को फिर से लिखना है ताकि इसका उपयोग एक उपश्रेणी के रूप में किया जा सके।

SELECT firstname, 
   lastname, 
   list.address 
FROM list
   INNER JOIN (SELECT address
               FROM   list
               GROUP  BY address
               HAVING COUNT(id) > 1) dup
           ON list.address = dup.address;

69
उप-प्रश्नों से सावधान रहें। उप-प्रश्न प्रदर्शन संबंधी चिंताओं के लिए हास्यास्पद रूप से बुरे हो सकते हैं। यदि यह अक्सर और / या बहुत सारे डुप्लिकेट रिकॉर्ड के साथ होने की आवश्यकता होती है, तो मैं डेटाबेस से बाहर और एक डेटासेट में प्रसंस्करण को स्थानांतरित करने पर विचार करूंगा।
bdwakefield

11
यह एक असंबंधित उपश्रेणी है, इसलिए इसे बहुत बुरा नहीं मानना ​​चाहिए कि या तो अकेले क्वेरी को खराब तरीके से डिज़ाइन नहीं किया गया है।
36ıu

लवली। लगता है कि यह "ERROR 1248 (42000) के आसपास का सिक्सैक्स है: प्रत्येक व्युत्पन्न तालिका का अपना उपनाम होना चाहिए"
डबलजॉश

3
यह सही विचार है, लेकिन फिर से, नीचे के रूप में, यह केवल तभी काम करता है जब पते को मानकीकृत करने की गारंटी दी जाती है ...
मैट

30
+1 इस क्वेरी के साथ आप डुप्लिकेट पा सकते हैं, लेकिन
ट्रिप्लिकेट्स

352
SELECT date FROM logs group by date having count(*) >= 2

5
लारवेल के साथ उपयोग करने के लिए यह सबसे आसान काम था। बस ->having(DB::raw('count(*)'), '>', 2)क्वेरी में जोड़ना था । बहुत धन्यवाद!
कोवह

1
10 मिलियन पंक्तियों की तालिका के साथ अच्छा काम करता है। यह सबसे अच्छा उत्तर होना चाहिए
टेरी लिन

13
इस उत्तर के साथ सावधान रहें। यह केवल एक डुप्लिकेट की वापसी करता है। यदि आपके पास एक ही रिकॉर्ड की 2 से अधिक प्रतियां हैं, तो आप उन सभी को नहीं देख पाएंगे, और वापस लौटाए गए रिकॉर्ड को हटाने के बाद भी आपकी तालिका में डुप्लिकेट होंगे।
मिकोको जेन

7
क्यों >=2? बस का उपयोग करेंHAVING COUNT(*) > 1
BadHorsie

2
@TerryLin यह मानते हुए कि यह वास्तव में मूल रूप से बताई गई समस्या को हल नहीं करता है (जो सभी डुप्लिकेट को कैसे वापस करना है) मैं असहमत हूं।
माइकल

198

क्यों न केवल अपने साथ टेबल शामिल करें?

SELECT a.firstname, a.lastname, a.address
FROM list a
INNER JOIN list b ON a.address = b.address
WHERE a.id <> b.id

यदि पता दो बार से अधिक मौजूद हो सकता है, तो DISTINCT की आवश्यकता है।


20
मैंने भी इसका परीक्षण किया, और यह मेरी स्थिति में स्वीकृत समाधान (नवीनतम MySQL, 120.000 पंक्तियों की तालिका) की तुलना में लगभग 6 गुना धीमा था। यह एक अस्थायी तालिका की आवश्यकता के कारण हो सकता है, अंतर देखने के लिए दोनों पर एक EXPLAIN चलाएँ।

4
मैंने WHERE a.id > b.idकेवल नए डुप्लिकेट को फ़िल्टर करने के लिए क्वेरी के अंतिम भाग को बदल दिया , इस तरह से मैं DELETEसीधे परिणाम पर कर सकता हूं । पुराने डुप्लिकेट को सूचीबद्ध करने के लिए तुलना स्विच करें।
स्टॉफ

1
इसे चलाने में 50 सेकंड लगे, @ doublejosh के जवाब में .13 सेकंड लगे।
एनाटागैस्टम

मुझे यह जोड़ना चाहिए कि यह जवाब डुप्लिकेट उत्तर देता है, जबकि एक पते के तिगुने होने के बावजूद, आउटपुट पंक्तियों को दोगुना किया जाता है। यदि यह चौगुना है, तो मेरा मानना ​​है कि प्रतिक्रिया तीन गुना हो जाएगी।
वली जूल

मैंने इसे लेटकोड " leetcode.com/problems/duplicate-emails " में परीक्षण किया । यह उप-क्वेरी की तुलना में तेज़ था।
तरंग

56

मैंने इस प्रश्न के लिए सबसे अच्छा उत्तर देने की कोशिश की, लेकिन इसने मुझे कुछ हद तक भ्रमित किया। मुझे वास्तव में अपनी मेज से एक ही मैदान पर जरूरत थी। इस लिंक से निम्नलिखित उदाहरण ने मेरे लिए बहुत अच्छा काम किया:

SELECT COUNT(*) c,title FROM `data` GROUP BY title HAVING c > 1;

एक जादू की तरह काम करता है!
विनीसस

47
select `cityname` from `codcities` group by `cityname` having count(*)>=2

यह उसी तरह की क्वेरी है जो आपने मांगी है और इसका 200% काम और आसान भी है। का आनंद लें!!!


37

क्या यह आसान नहीं है:

SELECT *
FROM tc_tariff_groups
GROUP BY group_id
HAVING COUNT(group_id) >1

?


1
मेरे लिए काम किया है जहाँ मुझे सिर्फ ~ १००० डुप्लिकेट पंक्तियों को प्रोसेस करना था ताकि उन्हें अद्वितीय बनाया जा सके, सभी ६०० ००० पंक्तियों को लोड करने की तुलना में बहुत तेज।
एड्रियनटाइन

1
बहुत आसान है
श्वेत

35

इस क्वेरी के साथ ईमेल पते द्वारा डुप्लिकेट उपयोगकर्ता खोजें ...

SELECT users.name, users.uid, users.mail, from_unixtime(created)
FROM users
INNER JOIN (
  SELECT mail
  FROM users
  GROUP BY mail
  HAVING count(mail) > 1
) dupes ON users.mail = dupes.mail
ORDER BY users.mail;

2
वास्तविक डुप्लिकेट को खोजने के लिए आपको केवल आंतरिक क्वेरी की आवश्यकता होती है। यह अन्य उत्तरों की तुलना में तेज़ है।
एनाटागैस्टम

20

हम पा सकते हैं कि डुप्लिकेट अधिक एक क्षेत्र पर भी निर्भर करता है। उन मामलों के लिए जिन्हें आप नीचे प्रारूप में उपयोग कर सकते हैं।

SELECT COUNT(*), column1, column2 
FROM tablename
GROUP BY column1, column2
HAVING COUNT(*)>1;

16

डुप्लिकेट पतों को ढूंढना जितना लगता है उससे कहीं अधिक जटिल है, खासकर यदि आपको सटीकता की आवश्यकता है। इस मामले में एक MySQL क्वेरी पर्याप्त नहीं है ...

मैं SmartyStreets पर काम करता हूं , जहां हम सत्यापन और डी-डुप्लीकेशन और अन्य सामान को संबोधित करते हैं, और मैंने इसी तरह की समस्याओं के साथ बहुत सारी विविध चुनौतियों को देखा है।

कई तृतीय-पक्ष सेवाएँ हैं जो आपके लिए एक सूची में डुप्लिकेट को फ़्लैग करेगी। पूरी तरह से MySQL उपकुंजी के साथ ऐसा करने से पता स्वरूपों और मानकों में अंतर नहीं होगा। यूएसपीएस (अमेरिका के पते के लिए) इन मानकों को बनाने के लिए कुछ दिशानिर्देश हैं, लेकिन ऐसे संचालन करने के लिए केवल मुट्ठी भर विक्रेताओं को प्रमाणित किया जाता है।

इसलिए, मैं आपके लिए सर्वोत्तम उत्तर देने की सिफारिश करूंगा कि तालिका को CSV फ़ाइल में निर्यात किया जाए, उदाहरण के लिए, और इसे सक्षम सूची प्रोसेसर में जमा करें। ऐसा ही एक SmartyStreets Bulk Address Validation Tool है, जो कुछ सेकंडों में आपके लिए कुछ ही मिनटों में अपने आप हो जाएगा। यह "डुप्लिकेट" नामक एक नए क्षेत्र के साथ डुप्लिकेट पंक्तियों को चिह्नित करेगा और इसमें एक मूल्य Yहोगा।


6
पते के तार में मिलान करने में कठिनाई को देखने के लिए +1, हालांकि आप यह निर्दिष्ट करना चाह सकते हैं कि ओपी का "डुप्लिकेट रिकॉर्ड" प्रश्न अपने आप में जटिल नहीं है, लेकिन जब पते की तुलना की जाती है
कहानी

13

एक अन्य उपाय यह होगा कि टेबल अलायसेस का उपयोग किया जाए, जैसे:

SELECT p1.id, p2.id, p1.address
FROM list AS p1, list AS p2
WHERE p1.address = p2.address
AND p1.id != p2.id

इस मामले में आप वास्तव में कर रहे हैं मूल सूची तालिका ले रहा है , दो पी रेटेंड टेबल बनाने - पी 1 और पी 2 - उस से बाहर है, और फिर पता स्तंभ (पंक्ति 3) पर एक प्रदर्शन कर रहा है। 4 वीं पंक्ति यह सुनिश्चित करती है कि आपके परिणामों के सेट ("डुप्लिकेट डुप्लिकेट") में एक ही रिकॉर्ड कई बार दिखाई नहीं देता है।


1
अच्छा काम करता है। अगर WHIKE LIKE से जाँच कर रहा है तो apostrophes भी पाए जाते हैं। क्वेरी को धीमा बनाता है, लेकिन मेरे मामले में यह एक-टाइमर है।
गोसी

10

बहुत कुशल नहीं है, लेकिन यह काम करना चाहिए:

SELECT *
FROM list AS outer
WHERE (SELECT COUNT(*)
        FROM list AS inner
        WHERE inner.address = outer.address) > 1;

10

यह एक तालिका पास, कोई उपश्रेणियों में डुप्लिकेट का चयन करेगा।

SELECT  *
FROM    (
        SELECT  ao.*, (@r := @r + 1) AS rn
        FROM    (
                SELECT  @_address := 'N'
                ) vars,
                (
                SELECT  *
                FROM
                        list a
                ORDER BY
                        address, id
                ) ao
        WHERE   CASE WHEN @_address <> address THEN @r := 0 ELSE 0 END IS NOT NULL
                AND (@_address := address ) IS NOT NULL
        ) aoo
WHERE   rn > 1

इस क्वेरी actially emulates ROW_NUMBER()वर्तमान में OracleऔरSQL Server

विवरण के लिए मेरे ब्लॉग में लेख देखें:


20
नाइटिकिक के लिए नहीं, बल्कि FROM (SELECT ...) aooएक उपश्रेणी है :-P
रॉकेट हज़मत

8

यह आपको यह भी दिखाएगा कि कितने डुप्लिकेट हैं और बिना जॉइन किए रिजल्ट ऑर्डर करेंगे

SELECT  `Language` , id, COUNT( id ) AS how_many
FROM  `languages` 
GROUP BY  `Language` 
HAVING how_many >=2
ORDER BY how_many DESC

यह सही है क्योंकि यह अभी भी कहता है कि कितने प्रविष्टियों को दोहराया गया है
डेनिस

4
 SELECT firstname, lastname, address FROM list
 WHERE 
 Address in 
 (SELECT address FROM list
 GROUP BY address
 HAVING count(*) > 1)

यह भी कोशिश की, लेकिन लगता है बस लटका। मानो आंतरिक क्वेरी से वापसी IN पैरामीटर प्रारूप को संतुष्ट नहीं करता है।
डबलजॉश

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

मुझे चिंता थी कि कॉलम के बजाय अल्पविराम से अलग की गई सूची आवश्यक थी, जो कि गलत थी। यहाँ मेरे लिए काम करने वाली क्वेरी है:SELECT users.name, users.uid, users.mail, from_unixtime(created) FROM users INNER JOIN ( SELECT mail FROM users GROUP BY mail HAVING count(mail) > 1 ) dup ON users.mail = dup.mail ORDER BY users.mail, users.created;
डबलूश

4
select * from table_name t1 inner join (select distinct <attribute list> from table_name as temp)t2 where t1.attribute_name = t2.attribute_name

आपकी तालिका के लिए यह कुछ ऐसा होगा

select * from list l1 inner join (select distinct address from list as list2)l2 where l1.address=l2.address

यह क्वेरी आपको आपकी सूची तालिका में सभी विशिष्ट पता प्रविष्टियाँ देगी ... मुझे यकीन नहीं है कि यह कैसे काम करेगा यदि आपके पास नाम, आदि के लिए कोई प्राथमिक कुंजी है।


4

सबसे तेज़ डुप्लिकेट हटाने की क्वेरी प्रक्रिया:

/* create temp table with one primary column id */
INSERT INTO temp(id) SELECT MIN(id) FROM list GROUP BY (isbn) HAVING COUNT(*)>1;
DELETE FROM list WHERE id IN (SELECT id FROM temp);
DELETE FROM temp;

2
यह स्पष्ट रूप से डुप्लिकेट के प्रत्येक समूह से केवल पहला रिकॉर्ड हटाता है।
पालक

4

व्यक्तिगत रूप से इस प्रश्न ने मेरी समस्या हल कर दी है:

SELECT `SUB_ID`, COUNT(SRV_KW_ID) as subscriptions FROM `SUB_SUBSCR` group by SUB_ID, SRV_KW_ID HAVING subscriptions > 1;

यह स्क्रिप्ट क्या करती है सब ग्राहक आईडी दिखा रही है जो तालिका में एक से अधिक बार मौजूद है और डुप्लिकेट की संख्या पाई गई है।

यह टेबल कॉलम हैं:

| SUB_SUBSCR_ID | int(11)     | NO   | PRI | NULL    | auto_increment |
| MSI_ALIAS     | varchar(64) | YES  | UNI | NULL    |                |
| SUB_ID        | int(11)     | NO   | MUL | NULL    |                |    
| SRV_KW_ID     | int(11)     | NO   | MUL | NULL    |                |

आशा है कि यह आपके लिए भी उपयोगी होगा!


3
SELECT t.*,(select count(*) from city as tt where tt.name=t.name) as count FROM `city` as t where (select count(*) from city as tt where tt.name=t.name) > 1 order by count desc

शहर को अपनी तालिका से बदलें । अपने फ़ील्ड नाम के साथ नाम बदलें



0
    Find duplicate Records:

    Suppose we have table : Student 
    student_id int
    student_name varchar
    Records:
    +------------+---------------------+
    | student_id | student_name        |
    +------------+---------------------+
    |        101 | usman               |
    |        101 | usman               |
    |        101 | usman               |
    |        102 | usmanyaqoob         |
    |        103 | muhammadusmanyaqoob |
    |        103 | muhammadusmanyaqoob |
    +------------+---------------------+

    Now we want to see duplicate records
    Use this query:


   select student_name,student_id ,count(*) c from student group by student_id,student_name having c>1;

+--------------------+------------+---+
| student_name        | student_id | c |
+---------------------+------------+---+
| usman               |        101 | 3 |
| muhammadusmanyaqoob |        103 | 2 |
+---------------------+------------+---+

0

डुप्लिकेट पंक्तियों को जल्दी से देखने के लिए आप एक सरल क्वेरी चला सकते हैं

यहां मैं तालिका क्वेरी कर रहा हूं और सभी डुप्लिकेट पंक्तियों को समान user_id, market_place और sku के साथ सूचीबद्ध कर रहा हूं:

select user_id, market_place,sku, count(id)as totals from sku_analytics group by user_id, market_place,sku having count(id)>1;

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

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

select a.user_id, a.market_place,a.sku from sku_analytics a inner join sku_analytics b where a.id< b.id and a.user_id= b.user_id and a.market_place= b.market_place and a.sku = b.sku;

फिर मैं डंप को हटाने के लिए डिलीट क्वेरी चलाता हूं:

delete a from sku_analytics a inner join sku_analytics b where a.id< b.id and a.user_id= b.user_id and a.market_place= b.market_place and a.sku = b.sku;

बैकअप, डबल चेक, सत्यापन, बैकअप की पुष्टि करें और फिर निष्पादित करें।


-1

select address from list where address = any (select address from (select address, count(id) cnt from list group by address having cnt > 1 ) as t1) order by address

आंतरिक उप-क्वेरी डुप्लिकेट पते के साथ पंक्तियाँ लौटाती है, फिर बाहरी उप-क्वेरी डुप्लिकेट वाले पते के लिए पता कॉलम लौटाती है। बाहरी उप-क्वेरी को केवल एक कॉलम वापस करना होगा क्योंकि यह ऑपरेटर के लिए ऑपरेंड '= किसी' के रूप में उपयोग किया जाता है


-1

पॉवरलॉर्ड उत्तर वास्तव में सबसे अच्छा है और मैं एक और बदलाव की सिफारिश करूंगा: यह सुनिश्चित करने के लिए लिमिट का उपयोग करें कि डीबी ओवरलोड नहीं होगा:

SELECT firstname, lastname, list.address FROM list
INNER JOIN (SELECT address FROM list
GROUP BY address HAVING count(id) > 1) dup ON list.address = dup.address
LIMIT 10

अगर कोई WHERE नहीं है और जॉइन करते समय LIMIT का उपयोग करना एक अच्छी आदत है। छोटे मूल्य से शुरू करें, जांचें कि क्वेरी कितनी भारी है और फिर सीमा बढ़ाएं।


यह किसी भी चीज़ में कुछ भी कैसे योगदान दे रहा है?
केनेट सेलेस्टे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.