MySQL में डुप्लिकेट मान ढूँढना


769

मेरे पास एक varchar स्तंभ के साथ एक तालिका है, और मैं इस कॉलम में डुप्लिकेट मान वाले सभी रिकॉर्ड ढूंढना चाहूंगा। डुप्लिकेट खोजने के लिए मैं सबसे अच्छी क्वेरी क्या उपयोग कर सकता हूं?


1
चूँकि आपने सभी अभिलेखों का उल्लेख किया है, इसलिए मैं मान रहा हूँ कि आपको कुंजी के साथ-साथ उस चर स्तंभ में डुप्लिकेट किए गए VALUES को जानना आवश्यक है।
TechTravelThink

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

जवाबों:


1521

SELECTएक GROUP BYखंड के साथ करो । मान लीजिए कि वह नाम है जिसमें आप डुप्लिकेट ढूंढना चाहते हैं:

SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 1;

यह पहले कॉलम में नाम मान के साथ एक परिणाम लौटाएगा , और दूसरे में मान कितनी बार दिखाई देगा इसकी एक गणना।


27
लेकिन यह कैसे उपयोगी है यदि आप डुप्लिकेट मान वाले पंक्तियों की आईडी प्राप्त नहीं कर सकते हैं? हां, आप प्रत्येक डुप्लिकेट मान के लिए एक नई क्वेरी मिलान कर सकते हैं, लेकिन क्या केवल डुप्लिकेट को सूचीबद्ध करना संभव है?
नोबल उत्थान

23
@ नोबल उत्थान आप कर सकते हैं GROUP_CONCAT(id)और यह आईडी की सूची देगा। एक उदाहरण के लिए मेरा जवाब देखें।
मैट रार्डन

5
अगर यह कहा जाता है तो इसका क्या मतलब होगा ERROR: column "c" does not exist LINE 1?
उपयोगकर्ता

15
मैं असमंजस में हूँ कि यह स्वीकृत उत्तर क्यों है और इसमें इतने उभार क्यों हैं। ओपी ने पूछा, "मैं इस कॉलम में डुप्लिकेट मान रखने वाले सभी रिकॉर्डों को खोजना चाहूंगा।" यह जवाब मायने रखता है की एक तालिका देता है। -1
मोनिका हेडडेक 20

4
उन लोगों के लिए जो यह नहीं समझते कि हविंग कैसे काम करता है - यह केवल परिणाम सेट पर एक फिल्टर है, इसलिए मुख्य क्वेरी के बाद होता है।
जॉन हंट

236
SELECT varchar_col
FROM table
GROUP BY varchar_col
HAVING COUNT(*) > 1;

10
सुपीरियर @ लेविक के उत्तर के बाद से यह एक अतिरिक्त कॉलम नहीं जोड़ता है। IN()/ के साथ उपयोग के लिए इसे उपयोगी बनाता है NOT IN()
वामासिंघम

172
SELECT  *
FROM    mytable mto
WHERE   EXISTS
        (
        SELECT  1
        FROM    mytable mti
        WHERE   mti.varchar_column = mto.varchar_column
        LIMIT 1, 1
        )

यह प्रश्न पूरा रिकॉर्ड देता है, न कि केवल अलग varchar_column

यह क्वेरी उपयोग नहीं करता है COUNT(*)। यदि बहुत सारे डुप्लिकेट हैं, COUNT(*)महंगा है, और आपको पूरी ज़रूरत नहीं है COUNT(*), तो आपको यह जानने की ज़रूरत है कि क्या समान मूल्य वाली दो पंक्तियाँ हैं।

varchar_columnनिश्चित रूप से इच्छाशक्ति पर एक सूचकांक होने से, इस क्वेरी को बहुत तेज़ करें।


3
बहुत अच्छा। मैंने ORDER BY varchar_column DESCक्वेरी के अंत में जोड़ा ।
त्रिनिडा

8
यह स्वीकार किए जाते हैं जवाब है, के रूप में होना चाहिए GROUP BYऔर HAVINGरिटर्न संभव डुप्लिकेट का केवल एक। इसके अलावा, के बजाय अनुक्रमित क्षेत्र के साथ प्रदर्शन COUNT(*), और ORDER BYडुप्लिकेट रिकॉर्ड समूह की संभावना ।
रेमी ब्रेटन

1
जैसा कि ऊपर टिप्पणियों में कहा गया है, यह क्वेरी आपको सभी डुप्लिकेट पंक्तियों को सूचीबद्ध करने की अनुमति देती है। बहुत उपयोगी।
ट्राइहार्डर

4
इसे देखकर मुझे समझ नहीं आया कि यह कैसे काम करेगा। अभ्यस्त आंतरिक स्थिति हमेशा सत्य होती है क्योंकि बाहरी तालिका में कोई भी पंक्ति आंतरिक तालिका में भी उपलब्ध होगी और इसलिए प्रत्येक पंक्ति हमेशा कम से कम अपने आप में ही होगी? मैंने क्वेरी की कोशिश की और परिणाम मुझे संदेह हुआ - हर पंक्ति वापस आ गई। लेकिन इतने उथल-पुथल के साथ मुझे खुद पर शक हो रहा है। क्या आंतरिक क्वेरी "और mto.id <> mti.id" जैसी कोई चीज़ नहीं है? जब मैं इसे जोड़ता हूं तो यह मेरे लिए काम करता है।
Clox

2
@Quassnoi ठीक है। मैंने इसे sqlfiddle पर डालने की कोशिश की है, लेकिन मैंने हर उस क्वेरी को छोड़ दिया है जिसे मैं चलाने की कोशिश करता हूं, इसके अलावा स्कीमा बनाने से समय समाप्त हो जाता है। मैंने यह पता लगाया कि "निष्कासन" को हटाने से क्वेरी का काम भी सही ढंग से हो जाता है।
Clox

144

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

SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUP BY name HAVING c > 1;

12
GROUP_CONCAT () के बारे में जाने बिना यह सब समय! बहुत उपयोगी है।
ऐसडे

वास्तव में मैट की सराहना की। यह वास्तव में उपयोगी है! Phpmyadmin में अपडेट करने की कोशिश करने वालों के लिए यदि आप आईडी को फंक्शन के साथ इस तरह छोड़ते हैं: SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]यह इनलाइन एडिटिंग को सक्षम करता है और इसमें शामिल सभी पंक्तियों को अपडेट करना चाहिए (या कम से कम पहले वाला मेल खाता है), लेकिन दुर्भाग्य से एडिट एक जावास्क्रिप्ट त्रुटि उत्पन्न करता है। ..
आर्मफुट

फिर आप कैसे गणना करेंगे कि कितने आईडी नकल के अधीन हैं?
CMCDragonkai

2
मुझे सभी ID के समूह कैसे नहीं मिलते, बल्कि पहले से लेकर अंतिम तक सूचीबद्ध हैं; अपने सभी संबंधित मानों के साथ कॉलम में उनके बगल में? इसलिए इसे समूहीकृत करने के बजाय, यह सिर्फ आईडी 1 और इसके मूल्य, आईडी 2 और इसके मूल्य को दिखाता है। EVEN यदि ID के लिए मान समान हैं।
मेलब्लेड

1
अत्यधिक सहायक उत्तर, यह शीर्ष होना चाहिए ताकि अधिक लोग इसे देखें। मुझे याद है कि इस तरह की सूचियों को बनाने में मुझे कितना दर्द हुआ था, और यह कमांड के रूप में हर समय उपलब्ध था ..
जॉन

13

मान लें कि आपकी तालिका का नाम TableABC है और जो कॉलम आप चाहते हैं वह Col है और T1 के लिए प्राथमिक कुंजी है।

SELECT a.Key, b.Key, a.Col 
FROM TableABC a, TableABC b
WHERE a.Col = b.Col 
AND a.Key <> b.Key

उपरोक्त उत्तर पर इस दृष्टिकोण का लाभ यह कुंजी देता है।


4
+1 क्योंकि यह आसान है। हालांकि, विडंबना यह है कि परिणाम में डुप्लिकेट शामिल हैं (यह ए और बी को सूचीबद्ध करता है, फिर बी और ए।)
फैबियन सन्नुअर्ट

2
@FabienSnauwaert आप कम से कम (या इससे अधिक) की तुलना करके कुछ डुप्लिकेट से छुटकारा पा सकते हैं
माइकल

@TechTravelThink आपका उत्तर बहुत स्पष्ट है, इसके लिए धन्यवाद, लेकिन बड़ी तालिका में कुछ समय लगता है (लगभग 20'000 से अधिक प्रविष्टियाँ तालिका पर 2mn) और 25 प्रथम परिणाम दिखाने के बाद, यदि मैं अगले एक को दिखाने के लिए क्लिक करता हूं, तो phpadadmin शो त्रुटि "# 1052 - क्रम खंड में कॉलम 'आईडी' अस्पष्ट है "
bcag2

12
SELECT * 
FROM `dps` 
WHERE pid IN (SELECT pid FROM `dps` GROUP BY pid HAVING COUNT(pid)>1)

1
नहीं, क्योंकि यह संभवतः बहुत से सबसे धीमा है। Subselects बेहद धीमी गति से होते हैं, क्योंकि वे हर पंक्ति के लिए निष्पादित होते हैं।
Oddman

10

यह जानने के लिए कि कर्मचारी में नाम कॉलम में कितने रिकॉर्ड डुप्लिकेट हैं, नीचे दी गई क्वेरी मददगार है;

Select name from employee group by name having count(*)>1;

10

सभी डेटा प्राप्त करने के लिए जिसमें डुप्लीकेशन शामिल है जिसका मैंने उपयोग किया है:

SELECT * FROM TableName INNER JOIN(
  SELECT DupliactedData FROM TableName GROUP BY DupliactedData HAVING COUNT(DupliactedData) > 1 order by DupliactedData)
  temp ON TableName.DupliactedData = temp.DupliactedData;

तालिका नाम = वह तालिका जिसके साथ आप काम कर रहे हैं।

डुप्लिकेटेडडाटा = जिस डुप्लीकेट डेटा की आप तलाश कर रहे हैं।


यह प्रत्येक पंक्ति में प्रत्येक डुप्लिकेट दिखाता है। मुझे इसी की जरूरत थी। धन्यवाद।
वार्मविस्की

8

मेरी अंतिम क्वेरी में कुछ उत्तरों को शामिल किया गया है जो मदद करते हैं - समूह के आधार पर, गणना और GROUP_CONCAT का संयोजन।

SELECT GROUP_CONCAT(id), `magento_simple`, COUNT(*) c 
FROM product_variant 
GROUP BY `magento_simple` HAVING c > 1;

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

तदनुसार तालिका और कॉलम बदलें।


8

मैं कोई जॉइन दृष्टिकोण नहीं देख रहा हूं, जिसमें डुप्लिकेट के संदर्भ में कई उपयोग हैं।

यह दृष्टिकोण आपको वास्तविक दोगुना परिणाम देता है।

SELECT t1.* FROM my_table as t1 
LEFT JOIN my_table as t2 
ON t1.name=t2.name and t1.id!=t2.id 
WHERE t2.id IS NOT NULL 
ORDER BY t1.name

2
FYI करें - आप 'अलग सोमेसोल का चयन करना चाहते हैं ..' अगर 1 से अधिक डुप्लिकेट रिकॉर्ड मौजूद होने की संभावना है अन्यथा परिणाम में डुप्लिकेट की गई पंक्तियों के डुप्लिकेट शामिल होंगे जो पाए गए थे।
ड्रयू

7
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

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


7

@ Maxyfc के उत्तर को और आगे ले जाते हुए , मुझे उन सभी पंक्तियों को खोजने की आवश्यकता थी, जिन्हें डुप्लिकेट मानों के साथ लौटाया गया था, इसलिए मैं उन्हें MySQL कार्यक्षेत्र में संपादित कर सकता हूं :

SELECT * FROM table
   WHERE field IN (
     SELECT field FROM table GROUP BY field HAVING count(*) > 1
   ) ORDER BY field

6

मैंने देखा कि उपरोक्त परिणाम और क्वेरी ठीक काम करेंगे यदि आपको एकल स्तंभ मान की जाँच करने की आवश्यकता है जो डुप्लिकेट हैं। उदाहरण के लिए ईमेल

लेकिन अगर आपको अधिक कॉलम के साथ जांच करने की आवश्यकता है और परिणाम के संयोजन की जांच करना चाहते हैं तो यह क्वेरी ठीक काम करेगी:

SELECT COUNT(CONCAT(name,email)) AS tot,
       name,
       email
FROM users
GROUP BY CONCAT(name,email)
HAVING tot>1 (This query will SHOW the USER list which ARE greater THAN 1
              AND also COUNT)

वास्तव में क्या जरूरत थी! यहाँ मेरी क्वेरी, डुप्लिकेट के लिए 3 क्षेत्रों की जाँच:SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
काई नैक

4

मैं डुप्लिकेट खोजने के लिए विंडो किए गए फ़ंक्शंस (MySQL 8.0+) का उपयोग करना पसंद करता हूं क्योंकि मैं पूरी पंक्ति देख सकता था:

WITH cte AS (
  SELECT *
    ,COUNT(*) OVER(PARTITION BY col_name) AS num_of_duplicates_group
    ,ROW_NUMBER() OVER(PARTITION BY col_name ORDER BY col_name2) AS pos_in_group
  FROM table
)
SELECT *
FROM cte
WHERE num_of_duplicates_group > 1;

डीबी फ़िडल डेमो


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

1
एक ही उपशम को करना दो बार अक्षम लगता है।
नोबल अपलिफ्ट

3

निम्नलिखित सभी product_id को एक से अधिक बार उपयोग किए जाते हैं। आपको प्रत्येक product_id के लिए केवल एक ही रिकॉर्ड मिलता है।

SELECT product_id FROM oc_product_reward GROUP BY product_id HAVING count( product_id ) >1

से लिया गया कोड: http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-any.html


3
CREATE TABLE tbl_master
    (`id` int, `email` varchar(15));

INSERT INTO tbl_master
    (`id`, `email`) VALUES
    (1, 'test1@gmail.com'),
    (2, 'test2@gmail.com'),
    (3, 'test1@gmail.com'),
    (4, 'test2@gmail.com'),
    (5, 'test5@gmail.com');

QUERY : SELECT id, email FROM tbl_master
WHERE email IN (SELECT email FROM tbl_master GROUP BY email HAVING COUNT(id) > 1)

2
SELECT DISTINCT a.email FROM `users` a LEFT JOIN `users` b ON a.email = b.email WHERE a.id != b.id;

1
वर्थ यह देखते हुए कि यह असहनीय रूप से धीमा है या समाप्त भी नहीं हो सकता है यदि स्तंभ के लिए क्वेरी की जा रही अनुक्रमित नहीं है। अन्यथा, मैं बदलने में सक्षम था a.emailकरने के लिए a.*और डुप्लिकेट के साथ पंक्तियों के सभी आईडी मिलता है।
नोबल उत्थान 14

@ नोबल उत्थान आप किस बारे में बात कर रहे हैं?
माइकल

@ मिचेल ठीक है क्योंकि यह तीन साल पुराना है, मैं MySQL के जिस भी संस्करण का उपयोग कर रहा था, उस पर परीक्षण नहीं कर सकता, लेकिन मैंने एक डेटाबेस पर उसी क्वेरी की कोशिश की, जहां मैंने जिस कॉलम को चुना था, उस पर कोई इंडेक्स नहीं था, इसलिए इसे काफी लिया गया खत्म करने के लिए कुछ सेकंड। इसे SELECT DISTINCT a.*लगभग तुरंत हल करने के लिए बदल रहा है ।
नोबल उत्थान

@ नोबलअपलिफ्ट आह ओके। मैं इसे धीमा होने के बारे में समझ सकता हूं ... जिस हिस्से को लेकर मैं चिंतित हूं वह "शायद खत्म भी न हो"।
माइकल

@ मिचेल मुझे याद नहीं है कि हमारे सिस्टम में कौन सी टेबल है जिस पर मुझे यह क्वेरी चलानी थी, लेकिन कुछ मिलियन रिकॉर्ड्स के साथ जो वे शायद खत्म कर चुके थे, लेकिन एक ऐसे समय में जब मुझे देखते हुए इतनी देर लग गई यह वास्तव में खत्म हो जाएगा।
नोबल उत्थान

1

कई फ़ील्ड्स के साथ डुप्लिकेट पंक्तियों को हटाने के लिए, पहले उन्हें नई विशिष्ट कुंजी को निर्दिष्ट करें जो केवल विशिष्ट पंक्तियों के लिए निर्दिष्ट है, फिर उसी नई अद्वितीय कुंजी के साथ डुप्लिकेट पंक्तियों को हटाने के लिए "आदेश" समूह का उपयोग करें:

Create TEMPORARY table tmp select concat(f1,f2) as cfs,t1.* from mytable as t1;
Create index x_tmp_cfs on tmp(cfs);
Create table unduptable select f1,f2,... from tmp group by cfs;

क्या आप एक स्पष्टीकरण भी जोड़ सकते हैं?
रॉबर्ट

उपयोग क्यों नहीं CREATE TEMPORARY TABLE ...? आपके समाधान की थोड़ी व्याख्या बहुत अच्छी होगी।
मैक्सहब

1

एक बहुत देर से योगदान ... मामले में यह किसी को भी लाइन से बाहर करने में मदद करता है ... मेरे पास एक बैंकिंग ऐप में लेनदेन के मिलान जोड़े (वास्तव में खाता-से-खाते के हस्तांतरण के दोनों पक्ष) को खोजने का एक काम था, जिससे लोगों की पहचान की जा सके प्रत्येक अंतर-खाता-हस्तांतरण लेनदेन के लिए 'से' और 'से' थे, इसलिए हमने इसे समाप्त किया:

SELECT 
    LEAST(primaryid, secondaryid) AS transactionid1,
    GREATEST(primaryid, secondaryid) AS transactionid2
FROM (
    SELECT table1.transactionid AS primaryid, 
        table2.transactionid AS secondaryid
    FROM financial_transactions table1
    INNER JOIN financial_transactions table2 
    ON table1.accountid = table2.accountid
    AND table1.transactionid <> table2.transactionid 
    AND table1.transactiondate = table2.transactiondate
    AND table1.sourceref = table2.destinationref
    AND table1.amount = (0 - table2.amount)
) AS DuplicateResultsTable
GROUP BY transactionid1
ORDER BY transactionid1;

इसका परिणाम यह होता है कि DuplicateResultsTableमिलान (यानी डुप्लिकेट) लेन-देन वाली पंक्तियाँ प्रदान करता है, लेकिन यह उसी लेन-देन आईडी को दूसरी बार उलट देता है, यह एक ही जोड़ी से मेल खाता है, इसलिए बाहरी SELECTवहाँ पहले लेनदेन आईडी द्वारा समूह में किया जाता है, जो किया जाता है उपयोग करके LEASTऔर GREATESTयह सुनिश्चित करने के लिए कि दो लेन-देनकर्ता हमेशा परिणामों में एक ही क्रम में होते हैं, जो इसे GROUPपहले एक तक सुरक्षित बनाता है , इस प्रकार सभी डुप्लिकेट मैचों को समाप्त करता है। लगभग 2 मिलियन रिकॉर्ड्स के जरिए दौड़े और सिर्फ 2 सेकंड में 12,000+ मैचों की पहचान की। बेशक लेन-देन प्राथमिक सूचकांक है, जिसने वास्तव में मदद की।




1

यदि आप डुप्लिकेट उपयोग को दूर करना चाहते हैं DISTINCT

अन्यथा इस क्वेरी का उपयोग करें:

SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;


0

इस क्वेरी का उपयोग करने का प्रयास करें:

SELECT name, COUNT(*) value_count FROM company_master GROUP BY name HAVING value_count > 1;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.