এসকিউএল সার্ভারে সদৃশ সারিগুলি সন্ধান করা হচ্ছে


230

আমার কাছে সংস্থাগুলির একটি এসকিউএল সার্ভার ডাটাবেস রয়েছে এবং অনেকগুলি নকল সারি রয়েছে। আমি এই সমস্ত এবং দুপুরের পরিমাণ ধরে নিতে একটি নির্বাচিত বিবৃতি চালাতে চাই, তবে প্রতিটি সংস্থার সাথে সম্পর্কিত আইডিকেও ফিরিয়ে দিতে চাই।

মত একটি বিবৃতি:

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
@ স্টিম আপনি সঠিক: লক্ষ লক্ষ রেকর্ড সহ বৃহত্তর ডাটাবেসে এই উত্তরটি দক্ষ নয়। আইকুট দ্বারা জমা করা গ্রুপবি / উত্তর থাকা পছন্দ করুন, যা ডেটাবেস দ্বারা আরও ভালতর করা যেতে পারে। একটি ব্যতিক্রম: আমি জিনিসকে সহজ করার জন্য গণনা (*) এর পরিবর্তে গণনা (0) ব্যবহার করার পরামর্শ দিই।
মাইক খ্রিস্টান

1
@ মাইক - কেন গণনা (0) বনাম গণনা (*)?
KornMuffin

2
@ কর্নমফিন প্রত্যক্ষদর্শী প্রতিবেদনে, গণনা সম্পর্কে আমার মন্তব্যটি বাতিল। কাউন্ট ()-এ একটি নন-নাল মূল্যায়ন ব্যবহার কেবলমাত্র তখনই কার্যকর যখন আপনি বহিরাগত যোগ দিয়ে ফিরে আসা নন-নাল ফলাফল গণনা করতে চান। অন্যথায়, গণনা (*) ব্যবহার করুন। একটি দুর্দান্ত ব্যাখ্যা এখানে পাওয়া যায় ।
মাইক ক্রিশ্চিয়ান

বিভাগে isnull()নালামযোগ্য কলামগুলির জন্য ব্যবহার করুনon
আরিফ উলুসয়

92

আপনি নিম্নলিখিত কোয়েরিটি চালনা করতে পারেন এবং সেই নকলগুলি সহ সদৃশগুলি সন্ধান max(id)এবং মুছতে পারেন।

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

তবে আপনাকে এই ক্যোয়ারীটি কয়েকবার চালাতে হবে।


আপনাকে এটিকে ঠিক MAX( COUNT(*) ) - 1সময়ে চালাতে হবে যা এখনও সম্ভব হবে।
ডারমাইক

1
হাই কি তাদের সমস্ত উপায় আইডি এর পরিবর্তে সর্বোচ্চ আইডির পরিবর্তে 2 এর জন্য আমি সর্বোচ্চ এবং মিনিট ব্যবহার করতে পারি তবে 2 এর বেশি কী? @ ডেরমাইক
অরিজিৎ মুখোপাধ্যায়

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

সম্পাদনা করুন: এসকিউএল সার্ভার 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

প্রথম বিবৃতিটি কাজ করে তবে দ্বিতীয়টি কাজ করে বলে মনে হয় না।
xtine

এসকিউএল সার্ভারটি রো-সংখ্যা () সনাক্ত করতে সক্ষম হবে বলে মনে হচ্ছে না?
xtine

আহ ... আপনার কি এসকিউএল সার্ভারের একটি পুরানো সংস্করণ আছে? আমি বিশ্বাস করি এটি এসকিউএল সার্ভার 2005
Paul

3
আবার ধন্যবাদ, আমি যখনই এটি করা দরকার
ততবারই

9

সঠিক হিসাবে চিহ্নিত সমাধানটি আমার পক্ষে কাজ করে নি, তবে আমি এই উত্তরটি পেয়েছি যা দুর্দান্ত কাজ করেছে: মাইএসকিউএলে সদৃশ সারিগুলির তালিকা পান My

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) গ্রুপবাই ব্যবহার করে

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

এটি এখানে সবচেয়ে দ্রুত সমাধান, যখন 10 মিটারের বেশি সারিগুলিতে ডেটা নির্বাচন করুন। ধন্যবাদ
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 এর সাথে থাকা রেকর্ডগুলি আপনার টেবিলের নকল রেকর্ড হবে। রেকর্ড অনুসারে প্রথম বিভাগ দ্বারা 'পার্টিশন' এবং তারপরে তাদের সিরিয়াল নম্বর দিয়ে সিরিয়ালিয়াল করুন। সুতরাং rownum> 1 হ'ল সদৃশ রেকর্ডগুলি যা মুছে ফেলা হতে পারে।


আমি এটি পছন্দ করি কারণ এটি আপনাকে অভ্যন্তরীণ নির্বাচনের ধারাটিতে সহজেই আরও কলাম যুক্ত করতে দেয়। সুতরাং আপনি যদি 'সংস্থাগুলি' সারণী থেকে অন্যান্য কলামগুলি ফিরে আসতে চান তবে আপনাকে এই কলামগুলিতে 'গ্রুপ বাই' করতে হবে না।
গওয়াস্প্প্পা


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

আপনি নির্বাচন জন্য বিভিন্ন উপায় আছে 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

ধরুন আমাদের কাছে দুটি কলাম সহ টেবিল 'ছাত্র' রয়েছে:

  • 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

উপরোক্ত ক্যোয়ারীর ফলাফলগুলি অনন্য ছাত্র আইডিসহ সমস্ত সদৃশ নাম এবং নকল ঘটনার সংখ্যা দেখায়

বর্গের ফলাফল দেখতে এখানে ক্লিক করুন



0

সদৃশ সারিগুলি সন্ধান করতে আমি দুটি পদ্ধতি ব্যবহার করি। 1 ম পদ্ধতিটি হ'ল গ্রুপটি ব্যবহার করে এবং করা সর্বাধিক বিখ্যাত। ২ য় পদ্ধতিটি সিটিই ব্যবহার করছে - সাধারণ টেবিল এক্সপ্রেশন

@ রেডফিল্টার দ্বারা উল্লিখিত হিসাবে এইভাবে সঠিক। অনেক সময় আমি খুঁজে পাই সিটিই পদ্ধতিটিও আমার পক্ষে দরকারী।

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 এবং PARTITION BY ব্যবহার করে পুনরাবৃত্তি ঘটনার সন্ধান করে ফলাফল সংগ্রহ করেছি। তারপরে আমরা প্রয়োগ করেছি যেখানে কেবলমাত্র সারিগুলি নির্বাচন করার জন্য ধারাটি রয়েছে যা পুনরাবৃত্ত গণনা ১ এরও বেশি রয়েছে All সমস্ত ফলাফলটি সিটিই টেবিল সংগ্রহ করা হয় এবং সংস্থা টেবিলের সাথে যোগ হয়।

সূত্র: কোডোবি


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.