SQL सर्वर में डुप्लिकेट पंक्तियाँ ढूँढना


231

मेरे पास संगठनों का एक SQL सर्वर डेटाबेस है, और कई डुप्लिकेट पंक्तियाँ हैं। मैं इन सभी और डूप्स की मात्रा को हथियाने के लिए एक चयन स्टेटमेंट चलाना चाहता हूं, लेकिन प्रत्येक संगठन के साथ जुड़ी आईडी भी लौटाता हूं।

एक बयान की तरह:

SELECT     orgName, COUNT(*) AS dupes  
FROM         organizations  
GROUP BY orgName  
HAVING      (COUNT(*) > 1)

कुछ इस तरह लौटेगा

orgName        | dupes  
ABC Corp       | 7  
Foo Federation | 5  
Widget Company | 2 

लेकिन मैं उनमें से आईडी भी हड़पना चाहता हूं। क्या इसे करने का कोई तरीका है? शायद ए की तरह

orgName        | dupeCount | id  
ABC Corp       | 1         | 34  
ABC Corp       | 2         | 5  
...  
Widget Company | 1         | 10  
Widget Company | 2         | 2  

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

जवाबों:


313
select o.orgName, oc.dupeCount, o.id
from organizations o
inner join (
    SELECT orgName, COUNT(*) AS dupeCount
    FROM organizations
    GROUP BY orgName
    HAVING COUNT(*) > 1
) oc on o.orgName = oc.orgName

4
क्या इस प्रश्न में कोई सीमाएँ हैं, उदाहरण के लिए यदि रिकॉर्ड की संख्या 10 मिलियन से अधिक है?
स्टीम

3
@Steam आप सही हैं: यह उत्तर लाखों रिकॉर्ड वाले बड़े डेटाबेस में कुशल नहीं है। Aykut द्वारा प्रस्तुत GroupBy / होने वाले उत्तर को प्राथमिकता दें, जिसे डेटाबेस द्वारा बेहतर रूप से अनुकूलित किया जा सकता है। एक अपवाद: मैं चीजों को आसान बनाने के लिए काउंट (*) के बजाय काउंट (0) का उपयोग करने का सुझाव देता हूं।
माइक क्रिस्चियन

1
@ माइक - क्यों गणना (0) बनाम गणना (*)?
कॉर्नमफिन

2
@KornMuffin रेट्रोस्पेक्ट में, काउंट पर मेरी टिप्पणी () शून्य है। गणना में गैर-अशक्त मूल्यांकन का उपयोग करना () केवल तब उपयोगी होता है जब आप बाहरी जुड़ाव द्वारा लौटाए गए गैर-शून्य परिणामों को गिनना चाहते हैं। अन्यथा, गणना (*) का उपयोग करें। एक महान स्पष्टीकरण यहाँ पाया जाता है
माइक क्रिश्चियन

खंड isnull()पर अशक्त स्तंभों के लिए उपयोगon
आरिफ उलसॉय

92

आप निम्न क्वेरी चला सकते हैं max(id)और उन पंक्तियों को हटा सकते हैं और डुप्लिकेट पा सकते हैं ।

SELECT orgName, COUNT(*), Max(ID) AS dupes 
FROM organizations 
GROUP BY orgName 
HAVING (COUNT(*) > 1)

लेकिन आपको इस क्वेरी को कुछ बार चलाना होगा।


आपको इसे ठीक उसी MAX( COUNT(*) ) - 1समय चलाना होगा , जो अभी भी संभव है।
DerMike

1
hi उनका कोई तरीका है कि सभी आईडी के बजाय 2 के लिए अधिकतम आईडी की तरह मैं अधिकतम और न्यूनतम का उपयोग कर सकता हूं लेकिन 2 से अधिक के बारे में क्या? @DerMike
अरिजीत मुखर्जी

31

आप इसे इस तरह से कर सकते हैं:

SELECT
    o.id, o.orgName, d.intCount
FROM (
     SELECT orgName, COUNT(*) as intCount
     FROM organizations
     GROUP BY orgName
     HAVING COUNT(*) > 1
) AS d
    INNER JOIN organizations o ON o.orgName = d.orgName

यदि आप केवल उन रिकॉर्ड्स को वापस करना चाहते हैं जिन्हें हटाया जा सकता है (प्रत्येक में से एक को छोड़कर), आप उपयोग कर सकते हैं:

SELECT
    id, orgName
FROM (
     SELECT 
         orgName, id,
         ROW_NUMBER() OVER (PARTITION BY orgName ORDER BY id) AS intRow
     FROM organizations
) AS d
WHERE intRow != 1

संपादित करें: SQL सर्वर 2000 में ROW_NUMBER () फ़ंक्शन नहीं है। इसके बजाय, आप उपयोग कर सकते हैं:

SELECT
    o.id, o.orgName, d.intCount
FROM (
     SELECT orgName, COUNT(*) as intCount, MIN(id) AS minId
     FROM organizations
     GROUP BY orgName
     HAVING COUNT(*) > 1
) AS d
    INNER JOIN organizations o ON o.orgName = d.orgName
WHERE d.minId != o.id

पहला कथन काम करता है, लेकिन दूसरा काम नहीं करता है।
०२

SQL सर्वर row_number () को पहचानने में सक्षम नहीं लगता है?
20

आह ... क्या आपके पास SQL ​​सर्वर का पुराना संस्करण है? मेरा मानना है कि यह SQL सर्वर 2005 में पेश किया गया था
पॉल

3
धन्यवाद फिर से, हर बार जब मुझे ऐसा करने की आवश्यकता होती है, तो मैं यहां
पहुंचता हूं

9

सही के रूप में चिह्नित समाधान मेरे लिए काम नहीं करता था, लेकिन मुझे यह उत्तर मिला जो बहुत अच्छा काम करता था: MySql में डुप्लिकेट पंक्तियों की सूची प्राप्त करें

SELECT n1.* 
FROM myTable n1
INNER JOIN myTable n2 
ON n2.repeatedCol = n1.repeatedCol
WHERE n1.id <> n2.id

आपको रिजल्ट सेट में बहुत सारे डाउट्स मिलेंगे, इसलिए आपको इनसे भी निपटना होगा।
रेनान

1
यदि आईडी संख्यात्मक है, तो जाँच n1.id > n2.idप्रत्येक जोड़ी को दो बार दिखाने से रोकेगी।
starwed

9

आप यह कोशिश कर सकते हैं, यह आपके लिए सबसे अच्छा है

 WITH CTE AS
    (
    SELECT *,RN=ROW_NUMBER() OVER (PARTITION BY orgName ORDER BY orgName DESC) FROM organizations 
    )
    select * from CTE where RN>1
    go

अल्पविराम या अलग कॉलम में सभी आईडी प्राप्त करने का कोई तरीका
अरिजीत मुखर्जी

6

यदि आप डुप्लिकेट हटाना चाहते हैं:

WITH CTE AS(
   SELECT orgName,id,
       RN = ROW_NUMBER()OVER(PARTITION BY orgName ORDER BY Id)
   FROM organizations
)
DELETE FROM CTE WHERE RN > 1

6
select * from [Employees]

डुप्लिकेट रिकॉर्ड खोजने के लिए 1) सीटीई का उपयोग करना

with mycte
as
(
select Name,EmailId,ROW_NUMBER() over(partition by Name,EmailId order by id) as Duplicate from [Employees]
)
select * from mycte

2) GroupBy का उपयोग करके

select Name,EmailId,COUNT(name) as Duplicate from  [Employees] group by Name,EmailId 

यह सबसे तेज़ समाधान है, जब 10m पंक्तियों पर डेटा का चयन करना। धन्यवाद
Fandango68

4
Select * from (Select orgName,id,
ROW_NUMBER() OVER(Partition By OrgName ORDER by id DESC) Rownum
From organizations )tbl Where Rownum>1

तो पंक्तिबद्ध> 1 के रिकॉर्ड आपकी तालिका में डुप्लिकेट रिकॉर्ड होंगे। रिकॉर्ड्स द्वारा 'पहले समूह द्वारा विभाजन' और फिर उन्हें सीरियल नग देकर उन्हें क्रमबद्ध करें। तो पंक्तिबद्ध> 1 डुप्लिकेट रिकॉर्ड होगा जिसे इस प्रकार हटाया जा सकता है।


मुझे यह पसंद है क्योंकि यह आपको आसानी से आंतरिक चयन खंड में अधिक कॉलम जोड़ने की अनुमति देता है। इसलिए यदि आप 'ऑर्गनाइजेशन' टेबल से अन्य कॉलमों को वापस करना चाहते हैं तो आपको उन कॉलमों पर 'ग्रुप बाय' नहीं करना है।
गावसोप्पा

2
select column_name, count(column_name)
from table_name
group by column_name
having count (column_name) > 1;

Src: https://stackoverflow.com/a/59242/1465252


यह केवल उन तालिकाओं पर काम करेगा जिनके पास एक एकल स्तंभ है। जो शायद सबसे ज्यादा उपयोगी नहीं है
Zach Smith

2
select a.orgName,b.duplicate, a.id
from organizations a
inner join (
    SELECT orgName, COUNT(*) AS duplicate
    FROM organizations
    GROUP BY orgName
    HAVING COUNT(*) > 1
) b on o.orgName = oc.orgName
group by a.orgName,a.id

1
select orgname, count(*) as dupes, id 
from organizations
where orgname in (
    select orgname
    from organizations
    group by orgname
    having (count(*) > 1)
)
group by orgname, id

1

आपके पास Select के लिए कई तरीके हैं duplicate rows

मेरे समाधान के लिए, पहले इस तालिका पर विचार करें

CREATE TABLE #Employee
(
ID          INT,
FIRST_NAME  NVARCHAR(100),
LAST_NAME   NVARCHAR(300)
)

INSERT INTO #Employee VALUES ( 1, 'Ardalan', 'Shahgholi' );
INSERT INTO #Employee VALUES ( 2, 'name1', 'lname1' );
INSERT INTO #Employee VALUES ( 3, 'name2', 'lname2' );
INSERT INTO #Employee VALUES ( 2, 'name1', 'lname1' );
INSERT INTO #Employee VALUES ( 3, 'name2', 'lname2' );
INSERT INTO #Employee VALUES ( 4, 'name3', 'lname3' );

पहला उपाय:

SELECT DISTINCT *
FROM   #Employee;

WITH #DeleteEmployee AS (
                     SELECT ROW_NUMBER()
                            OVER(PARTITION BY ID, First_Name, Last_Name ORDER BY ID) AS
                            RNUM
                     FROM   #Employee
                 )

SELECT *
FROM   #DeleteEmployee
WHERE  RNUM > 1

SELECT DISTINCT *
FROM   #Employee

सुरक्षित समाधान: identityफ़ील्ड का उपयोग करें

SELECT DISTINCT *
FROM   #Employee;

ALTER TABLE #Employee ADD UNIQ_ID INT IDENTITY(1, 1)

SELECT *
FROM   #Employee
WHERE  UNIQ_ID < (
    SELECT MAX(UNIQ_ID)
    FROM   #Employee a2
    WHERE  #Employee.ID = a2.ID
           AND #Employee.FIRST_NAME = a2.FIRST_NAME
           AND #Employee.LAST_NAME = a2.LAST_NAME
)

ALTER TABLE #Employee DROP COLUMN UNIQ_ID

SELECT DISTINCT *
FROM   #Employee

और सभी समाधान के अंत में इस कमांड का उपयोग करें

DROP TABLE #Employee

0

मुझे लगता है कि मुझे पता है कि आपको उत्तर के बीच मिश्रण करने के लिए मुझे क्या चाहिए, और मुझे लगता है कि मुझे वह समाधान मिल गया जो वह चाहता था:

select o.id,o.orgName, oc.dupeCount, oc.id,oc.orgName
from organizations o
inner join (
    SELECT MAX(id) as id, orgName, COUNT(*) AS dupeCount
    FROM organizations
    GROUP BY orgName
    HAVING COUNT(*) > 1
) oc on o.orgName = oc.orgName

अधिकतम आईडी होने से आपको डीबेट की आईडी और मूल में से एक मिलेगा जो उसने मांगा था:

id org name , dublicate count (missing out in this case) 
id doublicate org name , doub count (missing out again because does not help in this case)

केवल दुख की बात है कि आप इसे इस रूप में सामने लाते हैं

id , name , dubid , name

आशा है कि यह अभी भी मदद करता है


0

मान लें कि हमारे पास 2 स्तंभों के साथ तालिका 'छात्र' है:

  • student_id int
  • student_name varchar

    Records:
    +------------+---------------------+
    | student_id | student_name        |
    +------------+---------------------+
    |        101 | usman               |
    |        101 | usman               |
    |        101 | usman               |
    |        102 | usmanyaqoob         |
    |        103 | muhammadusmanyaqoob |
    |        103 | muhammadusmanyaqoob |
    +------------+---------------------+

अब हम डुप्लिकेट रिकॉर्ड देखना चाहते हैं इस क्वेरी का उपयोग करें:

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

मुझे डुप्लिकेट रिकॉर्ड्स को एक तालिका में प्राप्त करने का एक बेहतर विकल्प मिला

SELECT x.studid, y.stdname, y.dupecount
FROM student AS x INNER JOIN
(SELECT a.stdname, COUNT(*) AS dupecount
FROM student AS a INNER JOIN
studmisc AS b ON a.studid = b.studid
WHERE (a.studid LIKE '2018%') AND (b.studstatus = 4)
GROUP BY a.stdname
HAVING (COUNT(*) > 1)) AS y ON x.stdname = y.stdname INNER JOIN
studmisc AS z ON x.studid = z.studid
WHERE (x.studid LIKE '2018%') AND (z.studstatus = 4)
ORDER BY x.stdname

उपरोक्त क्वेरी का परिणाम अद्वितीय छात्र आईडी और डुप्लिकेट घटनाओं की संख्या के साथ सभी डुप्लिकेट नाम दिखाता है

Sql का परिणाम देखने के लिए यहां क्लिक करें



0

मैं दो पंक्तियों का उपयोग डुप्लिकेट पंक्तियों को खोजने के लिए करता हूं। 1st मेथड, ग्रुप होने और होने का उपयोग करने वाला सबसे प्रसिद्ध है। दूसरा तरीका सीटीई - कॉमन टेबल एक्सप्रेशन का उपयोग कर रहा है ।

जैसा कि @RedFilter ने बताया है कि यह सही भी है। कई बार मुझे लगता है कि सीटीई पद्धति मेरे लिए भी उपयोगी है।

WITH TempOrg (orgName,RepeatCount)
AS
(
SELECT orgName,ROW_NUMBER() OVER(PARTITION by orgName ORDER BY orgName) 
AS RepeatCount
FROM dbo.organizations
)
select t.*,e.id from organizations   e
inner join TempOrg t on t.orgName= e.orgName
where t.RepeatCount>1

ऊपर के उदाहरण में हमने ROW_NUMBER और पार्टीशन BY का उपयोग करके पुनरावृत्ति प्राप्त करके परिणाम एकत्र किया। फिर हमने आवेदन किया जहां क्लॉज़ केवल उन पंक्तियों का चयन करने के लिए हैं जो 1. से अधिक की गिनती को दोहराते हैं। सभी परिणाम CTE तालिका एकत्र किए जाते हैं और संगठन तालिका के साथ जुड़ जाते हैं।

स्रोत: कोडोबी


-2

प्रयत्न

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