Tek bir alanla kopyaları bulmak kolaydır:
SELECT name, COUNT(email)
FROM users
GROUP BY email
HAVING COUNT(email) > 1
Yani eğer bir tablomuz varsa
ID NAME EMAIL
1 John [email protected]
2 Sam [email protected]
3 Tom [email protected]
4 Bob [email protected]
5 Tom [email protected]
Bu sorgu bize John, Sam, Tom, Tom'u verecektir çünkü hepsi aynı email
e sahiptir.
Ancak, istediğim şey aynı email
ve name
ile kopyaları almak.
Yani, "Tom", "Tom"'u almak istiyorum.
Buna ihtiyacım olmasının sebebi: Bir hata yaptım ve yinelenen name
ve email
değerlerinin eklenmesine izin verdim. Şimdi kopyaları kaldırmam/değiştirmem gerekiyor, bu yüzden önce onları bulmam gerekiyor.
SELECT
name, email, COUNT(*)
FROM
users
GROUP BY
name, email
HAVING
COUNT(*) > 1
Her iki sütunda da gruplama yapmanız yeterlidir.
Not: Eski ANSI standardı, GROUP BY içinde tüm toplanmamış sütunların bulunmasıdır, ancak bu "işlevsel bağımlılık" fikriyle değişmiştir:
İlişkisel veritabanı teorisinde, işlevsel bağımlılık, bir veritabanındaki bir ilişkideki iki nitelik kümesi arasındaki bir kısıtlamadır. Başka bir deyişle, fonksiyonel bağımlılık, bir ilişkideki nitelikler arasındaki ilişkiyi tanımlayan bir kısıtlamadır.
Destek tutarlı değildir:
sql_mode=only_full_group_by
kullanmanız gerekir:Bunu dene:
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
ÇIKIŞ:
name email CountOf
---------- ----------- -----------
John John-email 2
sam sam-email 2
(2 row(s) affected)
eğer yedeklerin ID'lerini istiyorsanız bunu kullanın:
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
ÇIKIŞ:
id name email
----------- ---------- ------------
1 John John-email
2 John John-email
5 sam sam-email
6 sam sam-email
(4 row(s) affected)
kopyaları silmek için deneyin:
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
ÇIKIŞ:
id name email
----------- ---------- --------------
1 John John-email
3 fred John-email
4 fred fred-email
5 sam sam-email
(4 row(s) affected)