Câu hỏi Tìm các giá trị trùng lặp trong một bảng SQL


Thật dễ dàng để tìm duplicates với một trường:

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

Vì vậy, nếu chúng ta có một bảng

ID   NAME   EMAIL
1    John   asd@asd.com
2    Sam    asd@asd.com
3    Tom    asd@asd.com
4    Bob    bob@asd.com
5    Tom    asd@asd.com

Truy vấn này sẽ cung cấp cho chúng tôi John, Sam, Tom, Tom bởi vì tất cả chúng đều giống nhau email.

Tuy nhiên, những gì tôi muốn là để có được bản sao với cùng một email và name.

Đó là, tôi muốn nhận được "Tom", "Tom".

Lý do tôi cần điều này: Tôi đã mắc lỗi và được phép chèn bản sao name và email giá trị. Bây giờ tôi cần phải xóa / thay đổi các bản sao, vì vậy tôi cần tìm thấy đầu tiên.


1307
2018-04-07 18:17


gốc


Tôi không nghĩ rằng nó sẽ cho phép bạn chọn tên trong mẫu đầu tiên của bạn vì nó không có trong một hàm tổng hợp. "Số lượng địa chỉ email trùng khớp và tên của chúng là gì" là một số logic phức tạp ... - sXe
Hm ... làm thế nào mà câu hỏi này thực sự biến nó thành thư "tin tức" của tầng hầm 18 tháng 1? - syck


Các câu trả lời:


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

Chỉ cần nhóm trên cả hai cột.

Lưu ý: tiêu chuẩn ANSI cũ hơn là có tất cả các cột không được tổng hợp trong GROUP BY nhưng điều này đã thay đổi theo ý tưởng "phụ thuộc chức năng":

Trong lý thuyết cơ sở dữ liệu quan hệ, một phụ thuộc chức năng là một ràng buộc giữa hai tập hợp các thuộc tính trong một quan hệ từ một cơ sở dữ liệu. Nói cách khác, phụ thuộc chức năng là một ràng buộc mô tả mối quan hệ giữa các thuộc tính trong một mối quan hệ.

Hỗ trợ không nhất quán:


2131
2018-04-07 18:20



Phần tôi luôn luôn trống trên là HAVING. WHERE không hoạt động! - webXL
@webXL WHERE làm việc với một bản ghi HAVING hoạt động với nhóm - bjan
@gbn Có thể đưa Id vào kết quả không? Sau đó, sẽ dễ dàng hơn để xóa những bản sao đó sau đó. - user797717
@ user797717: bạn cần phải có MIN (ID) và sau đó xóa các giá trị ID không phải trong giá trị cuối cùng nếu MIN (ID) - gbn
@gbn Tuyệt vời. Cảm ơn. Tôi có thể thấy bây giờ ID của. - user797717


thử cái này:

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

ĐẦU RA:

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

(2 row(s) affected)

nếu bạn muốn các ID của các dups sử dụng điều này:

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

ĐẦU RA:

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

(4 row(s) affected)

để xóa các bản sao thử:

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

ĐẦU RA:

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

(4 row(s) affected)

275
2018-04-07 18:22





Thử cái này:

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

89
2018-04-07 18:20





Nếu bạn muốn xóa các bản sao, đây là một cách đơn giản hơn nhiều để làm điều đó hơn là phải tìm các hàng chẵn / lẻ thành một lựa chọn phụ ba:

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

Và như vậy để xóa:

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
)

Đọc và hiểu IMHO dễ dàng hơn nhiều

Chú thích: Vấn đề duy nhất là bạn phải thực hiện yêu cầu cho đến khi không có hàng nào bị xóa, vì bạn chỉ xóa 1 trong mỗi lần trùng lặp mỗi lần


42
2018-03-14 14:22



Đẹp và dễ đọc; Tôi muốn tìm một cách để xóa nhiều hàng trùng lặp trong một đi mặc dù. - Dickon Reed
Điều này không hiệu quả đối với tôi khi tôi nhận được You can't specify target table 'users' for update in FROM clause - Whitecat
@Whitecat có vẻ như một vấn đề MySQL đơn giản: stackoverflow.com/questions/4429319/… - AncAinu
Không cho tôi. Tôi nhận được: "DBD :: CSV :: st thực thi không thành công: Sử dụng giá trị uninitialized $ _ [1] trong phần tử băm tại /Users/hornenj/perl5/perlbrew/perls/perl-5.26.0/lib/site_perl/5.26. 0 / SQL / Eval.pm dòng 43 " - Nigel Horne


Hãy thử những điều sau đây:

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

30
2017-12-31 10:07



Một thay đổi nhỏ đối với SELECT * đã giúp tôi giải quyết một tìm kiếm trong một giờ. Tôi chưa bao giờ sử dụng OVER (PARTITION BY trước đây. Tôi không bao giờ ngừng ngạc nhiên trước việc có bao nhiêu cách để làm điều tương tự trong SQL! - Joe Ruder


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

22
2017-07-22 07:12





Một chút muộn để các bên nhưng tôi tìm thấy một workaround thực sự mát mẻ để tìm kiếm tất cả các ID trùng lặp:

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

17
2017-11-17 10:21



Xuất hiện để trở thành một công cụ đường thực tiễn. Nice tìm. - Chef_Code
Hãy nhớ rằng GROUP_CONCAT sẽ dừng sau một số độ dài được xác định trước, vì vậy bạn có thể không nhận được tất cả idS. - v010dya
GROUP_CONCAT không hoạt động trong PostgreSQL - Clint Eastwood


thử mã này

WITH CTE AS

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

15
2017-09-13 04:03





Trong trường hợp bạn làm việc với Oracle, cách này sẽ thích hợp hơn:

create table my_users(id number, name varchar2(100), email varchar2(100));

insert into my_users values (1, 'John', 'asd@asd.com');
insert into my_users values (2, 'Sam', 'asd@asd.com');
insert into my_users values (3, 'Tom', 'asd@asd.com');
insert into my_users values (4, 'Bob', 'bob@asd.com');
insert into my_users values (5, 'Tom', 'asd@asd.com');

commit;

select *
  from my_users
 where rowid not in (select min(rowid) from my_users group by name, email);

13
2018-06-16 08:50





Điều này sẽ chọn / xóa tất cả các bản ghi trùng lặp ngoại trừ một bản ghi từ mỗi nhóm các bản sao. Vì vậy, xóa bỏ tất cả các bản ghi duy nhất + một bản ghi từ mỗi nhóm các bản sao.

Chọn các bản sao:

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

Xóa bản sao:

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

Hãy nhận biết số lượng bản ghi lớn hơn, nó có thể gây ra các vấn đề về hiệu suất. 


12
2018-02-22 15:02



Lỗi trong truy vấn xóa - Bạn không thể chỉ định bảng mục tiêu 'thành phố' để cập nhật trong mệnh đề FROM - Ali Azhar
Không có bảng 'thành phố' cũng như điều khoản cập nhật. Ý anh là gì? Lỗi trong truy vấn xóa ở đâu? - Martin Silovský


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

8
2017-09-12 18:18