كيفية - مبادئ قواعد البيانات sql




العثور على قيم مكررة في جدول SQL (16)

إذا كنت ترغب في حذف التكرارات ، فإليك طريقة أبسط بكثير للقيام بذلك من البحث عن صفوف زوجية / فردية في اختيار فرعي ثلاثي:

SELECT id, name, email 
FROM users u, users u2
WHERE u.name = u2.name AND u.email = u2.email AND u.id > u2.id

وهكذا لحذف:

DELETE FROM users
WHERE id IN (
    SELECT id/*, name, email*/
    FROM users u, users u2
    WHERE u.name = u2.name AND u.email = u2.email AND u.id > u2.id
)

أسهل بكثير لقراءة وفهم IMHO

ملاحظة: المشكلة الوحيدة هي أنه يتعين عليك تنفيذ الطلب حتى لا يتم حذف صفوف ، نظرًا لأنك تقوم بحذف 1 فقط من كل تكرار في كل مرة

من السهل العثور على duplicates حقل واحد:

SELECT name, COUNT(email) 
FROM users
GROUP BY email
HAVING COUNT(email) > 1

لذلك إذا كان لدينا طاولة

ID   NAME   EMAIL
1    John   [email protected]
2    Sam    [email protected]
3    Tom    [email protected]
4    Bob    [email protected]
5    Tom    [email protected]

سيقدم لنا هذا الاستفسار John، Sam، Tom، Tom لأنهم جميعًا لديهم نفس email .

ومع ذلك ، ما أريده هو الحصول على نسخ مكررة باستخدام نفس email name .

هذا هو ، أريد الحصول على "توم" ، "توم".

السبب في أنني بحاجة إلى هذا: لقد ارتكبت خطأ ، وسمحت بإدخال name مكرر وقيم email . الآن أحتاج إلى إزالة / تغيير التكرارات ، لذا يجب أن أجدها أولاً.


إذا كنت ترغب في معرفة ما إذا كان هناك أي صفوف مكررة في جدولك ، فقد استخدمت أدناه طلب البحث:

create table my_table(id int, name varchar(100), email varchar(100));

insert into my_table values (1, 'shekh', '[email protected]');
insert into my_table values (1, 'shekh', '[email protected]');
insert into my_table values (2, 'Aman', '[email protected]');
insert into my_table values (3, 'Tom', '[email protected]');
insert into my_table values (4, 'Raj', '[email protected]');


Select COUNT(1) As Total_Rows from my_table 
Select Count(1) As Distinct_Rows from ( Select Distinct * from my_table) abc 

تأخرت قليلاً للحفل ولكنني وجدت حلًا رائعًا حقًا للعثور على جميع المكوّنات المكررة:

SELECT GROUP_CONCAT( id )
FROM users
GROUP BY email
HAVING ( COUNT(email) > 1 )

جرب هذا الكود

WITH CTE AS

( SELECT Id, Name, Age, Comments, RN = ROW_NUMBER()OVER(PARTITION BY Name,Age ORDER BY ccn)
FROM ccnmaster )
select * from CTE 

جرب هذا:

declare @YourTable table (id int, name varchar(10), email varchar(50))

INSERT @YourTable VALUES (1,'John','John-email')
INSERT @YourTable VALUES (2,'John','John-email')
INSERT @YourTable VALUES (3,'fred','John-email')
INSERT @YourTable VALUES (4,'fred','fred-email')
INSERT @YourTable VALUES (5,'sam','sam-email')
INSERT @YourTable VALUES (6,'sam','sam-email')

SELECT
    name,email, COUNT(*) AS CountOf
    FROM @YourTable
    GROUP BY name,email
    HAVING COUNT(*)>1

انتاج:

name       email       CountOf
---------- ----------- -----------
John       John-email  2
sam        sam-email   2

(2 row(s) affected)

إذا كنت تريد استخدام معرفات الخوادم هذه:

SELECT
    y.id,y.name,y.email
    FROM @YourTable y
        INNER JOIN (SELECT
                        name,email, COUNT(*) AS CountOf
                        FROM @YourTable
                        GROUP BY name,email
                        HAVING COUNT(*)>1
                    ) dt ON y.name=dt.name AND y.email=dt.email

انتاج:

id          name       email
----------- ---------- ------------
1           John       John-email
2           John       John-email
5           sam        sam-email
6           sam        sam-email

(4 row(s) affected)

لحذف النسخة المكررة ، حاول:

DELETE d
    FROM @YourTable d
        INNER JOIN (SELECT
                        y.id,y.name,y.email,ROW_NUMBER() OVER(PARTITION BY y.name,y.email ORDER BY y.name,y.email,y.id) AS RowRank
                        FROM @YourTable y
                            INNER JOIN (SELECT
                                            name,email, COUNT(*) AS CountOf
                                            FROM @YourTable
                                            GROUP BY name,email
                                            HAVING COUNT(*)>1
                                        ) dt ON y.name=dt.name AND y.email=dt.email
                   ) dt2 ON d.id=dt2.id
        WHERE dt2.RowRank!=1
SELECT * FROM @YourTable

انتاج:

id          name       email
----------- ---------- --------------
1           John       John-email
3           fred       John-email
4           fred       fred-email
5           sam        sam-email

(4 row(s) affected)

حاول القيام بما يلي:

SELECT * FROM
(
    SELECT Id, Name, Age, Comments, Row_Number() OVER(PARTITION BY Name, Age ORDER By Name)
        AS Rank 
        FROM Customers
) AS B WHERE Rank>1

كيف يمكننا حساب القيم المكررة؟ إما أنها تتكرر مرتين أو أكثر من 2. فقط عدّها ، وليس مجموعة حكيمة.

ببساطة

select COUNT(distinct col_01) from Table_01

هذا هو الشيء السهل الذي أتيت به يستخدم تعبير جدول شائع (CTE) ونافذة قسم (أعتقد أن هذه الميزات موجودة في SQL 2008 والإصدارات الأحدث).

يجد هذا المثال جميع الطلاب الذين لديهم اسم مكرر و dob. الحقول التي تريد التحقق من وجود تكرار لها في جملة OVER. يمكنك تضمين أي حقول أخرى تريدها في العرض.

with cte (StudentId, Fname, LName, DOB, RowCnt)
as (
SELECT StudentId, FirstName, LastName, DateOfBirth as DOB, SUM(1) OVER (Partition By FirstName, LastName, DateOfBirth) as RowCnt
FROM tblStudent
)
SELECT * from CTE where RowCnt > 1
ORDER BY DOB, LName

هذا يحدد / يحذف جميع السجلات المكررة باستثناء سجل واحد من كل مجموعة من التكرارات. لذلك ، يترك الحذف كل السجلات الفريدة + سجل واحد من كل مجموعة من التكرارات.

حدد التكرارات:

SELECT *
FROM table
WHERE
    id NOT IN (
        SELECT MIN(id)
        FROM table
        GROUP BY column1, column2
);

حذف التكرارات:

DELETE FROM table
WHERE
    id NOT IN (
        SELECT MIN(id)
        FROM table
        GROUP BY column1, column2
);

كن على دراية بكميات أكبر من السجلات ، يمكن أن يسبب مشاكل في الأداء.


SELECT column_name,COUNT(*) FROM TABLE_NAME GROUP BY column1, HAVING COUNT(*) > 1;


باستخدام CTE أيضا يمكننا أن نجد قيمة مكررة مثل هذا

with MyCTE
as
(
select Name,EmailId,ROW_NUMBER() over(PARTITION BY EmailId order by id) as Duplicate from [Employees]

)
select * from MyCTE where Duplicate>1

 SELECT name, email 
    FROM users
    WHERE email in
    (SELECT email FROM users
    GROUP BY email 
    HAVING COUNT(*)>1)

SELECT
    name, email, COUNT(*)
FROM
    users
GROUP BY
    name, email
HAVING 
    COUNT(*) > 1

ببساطة مجموعة على كل من الأعمدة.

ملاحظة: معيار ANSI هو أن يكون جميع الأعمدة غير المجمعة في GROUP BY. يتيح لك MySQL تجنب هذا ، ولكن النتائج غير متوقعة:

في MySQL أنت بحاجة إلى sql_mode=only_full_group_by


SELECT
  FirstName, LastName, MobileNo, COUNT(1) as CNT 
FROM        
  CUSTOMER
GROUP BY
  FirstName, LastName, MobileNo 
HAVING
  COUNT(1) > 1;

select id,name,COUNT(*) from India group by Id,Name having COUNT(*)>1

select name, email
, case 
when ROW_NUMBER () over (partition by name, email order by name) > 1 then 'Yes'
else 'No'
end "duplicated ?"
from users




duplicates