Tôi có một bảng với một cột varchar và tôi muốn tìm tất cả các bản ghi có giá trị trùng lặp trong cột này. Truy vấn tốt nhất tôi có thể sử dụng để tìm các bản sao là gì?
Tôi có một bảng với một cột varchar và tôi muốn tìm tất cả các bản ghi có giá trị trùng lặp trong cột này. Truy vấn tốt nhất tôi có thể sử dụng để tìm các bản sao là gì?
Câu trả lời:
Làm một SELECT
với một GROUP BY
mệnh đề. Giả sử tên là cột bạn muốn tìm bản sao trong:
SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 1;
Điều này sẽ trả về một kết quả với giá trị tên trong cột đầu tiên và đếm số lần giá trị đó xuất hiện trong lần thứ hai.
GROUP_CONCAT(id)
và nó sẽ liệt kê các ID. Xem câu trả lời của tôi cho một ví dụ.
ERROR: column "c" does not exist LINE 1
?
SELECT varchar_col
FROM table
GROUP BY varchar_col
HAVING COUNT(*) > 1;
IN()
/ NOT IN()
.
SELECT *
FROM mytable mto
WHERE EXISTS
(
SELECT 1
FROM mytable mti
WHERE mti.varchar_column = mto.varchar_column
LIMIT 1, 1
)
Truy vấn này trả về các bản ghi đầy đủ, không chỉ riêng biệt varchar_column
.
Truy vấn này không sử dụng COUNT(*)
. Nếu có nhiều bản sao, COUNT(*)
đắt tiền và bạn không cần toàn bộ COUNT(*)
, bạn chỉ cần biết nếu có hai hàng có cùng giá trị.
Tất nhiên, có một chỉ mục theo varchar_column
ý muốn, tăng tốc truy vấn này rất nhiều.
ORDER BY varchar_column DESC
cuối truy vấn.
GROUP BY
và HAVING
chỉ trả về một trong những trùng lặp có thể có. Ngoài ra, hiệu suất với trường được lập chỉ mục thay vì COUNT(*)
và khả năng ORDER BY
nhóm các bản ghi trùng lặp.
Dựa trên câu trả lời của levik để lấy ID của các hàng trùng lặp, bạn có thể thực hiện GROUP_CONCAT
nếu máy chủ của bạn hỗ trợ (điều này sẽ trả về danh sách id được phân tách bằng dấu phẩy).
SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUP BY name HAVING c > 1;
SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]
nó cho phép chỉnh sửa nội tuyến và nó sẽ cập nhật tất cả các hàng liên quan (hoặc ít nhất là hàng đầu tiên khớp), nhưng không may là chỉnh sửa tạo ra lỗi Javascript. ..
Giả sử bảng của bạn được đặt tên là TableABC và cột mà bạn muốn là Col và khóa chính cho T1 là Khóa.
SELECT a.Key, b.Key, a.Col
FROM TableABC a, TableABC b
WHERE a.Col = b.Col
AND a.Key <> b.Key
Ưu điểm của phương pháp này so với câu trả lời ở trên là nó cung cấp cho Key.
Để tìm xem có bao nhiêu bản ghi trùng lặp trong cột tên trong Nhân viên, truy vấn bên dưới là hữu ích;
Select name from employee group by name having count(*)>1;
để có được tất cả các dữ liệu có chứa bản sao tôi đã sử dụng:
SELECT * FROM TableName INNER JOIN(
SELECT DupliactedData FROM TableName GROUP BY DupliactedData HAVING COUNT(DupliactedData) > 1 order by DupliactedData)
temp ON TableName.DupliactedData = temp.DupliactedData;
TableName = bảng bạn đang làm việc.
DupliactedData = dữ liệu trùng lặp mà bạn đang tìm kiếm.
Truy vấn cuối cùng của tôi kết hợp một vài câu trả lời ở đây có ích - kết hợp nhóm theo, đếm & GROUP_CONCAT.
SELECT GROUP_CONCAT(id), `magento_simple`, COUNT(*) c
FROM product_variant
GROUP BY `magento_simple` HAVING c > 1;
Điều này cung cấp id của cả hai ví dụ (được phân tách bằng dấu phẩy), mã vạch tôi cần và có bao nhiêu bản sao.
Thay đổi bảng và cột cho phù hợp.
Tôi không thấy bất kỳ phương pháp THAM GIA nào, có nhiều cách sử dụng về mặt trùng lặp.
Cách tiếp cận này cung cấp cho bạn kết quả nhân đôi thực tế.
SELECT t1.* FROM my_table as t1
LEFT JOIN my_table as t2
ON t1.name=t2.name and t1.id!=t2.id
WHERE t2.id IS NOT NULL
ORDER BY t1.name
Đưa câu trả lời của @ maxyfc đi xa hơn, tôi cần tìm tất cả các hàng được trả về với các giá trị trùng lặp, để tôi có thể chỉnh sửa chúng trong MySQL Workbench :
SELECT * FROM table
WHERE field IN (
SELECT field FROM table GROUP BY field HAVING count(*) > 1
) ORDER BY field
Tôi thấy kết quả trên và truy vấn sẽ hoạt động tốt nếu bạn cần kiểm tra giá trị cột đơn trùng lặp. Ví dụ email.
Nhưng nếu bạn cần kiểm tra với nhiều cột hơn và muốn kiểm tra kết hợp kết quả để truy vấn này sẽ hoạt động tốt:
SELECT COUNT(CONCAT(name,email)) AS tot,
name,
email
FROM users
GROUP BY CONCAT(name,email)
HAVING tot>1 (This query will SHOW the USER list which ARE greater THAN 1
AND also COUNT)
SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
Tôi thích sử dụng các chức năng có cửa sổ (MySQL 8.0+) để tìm các bản sao vì tôi có thể thấy toàn bộ hàng:
WITH cte AS (
SELECT *
,COUNT(*) OVER(PARTITION BY col_name) AS num_of_duplicates_group
,ROW_NUMBER() OVER(PARTITION BY col_name ORDER BY col_name2) AS pos_in_group
FROM table
)
SELECT *
FROM cte
WHERE num_of_duplicates_group > 1;
SELECT
t.*,
(SELECT COUNT(*) FROM city AS tt WHERE tt.name=t.name) AS count
FROM `city` AS t
WHERE
(SELECT count(*) FROM city AS tt WHERE tt.name=t.name) > 1 ORDER BY count DESC
Sau đây sẽ tìm thấy tất cả sản phẩm được sử dụng nhiều lần. Bạn chỉ nhận được một bản ghi cho mỗi sản phẩm_id.
SELECT product_id FROM oc_product_reward GROUP BY product_id HAVING count( product_id ) >1
Mã được lấy từ: http://framreshrana.blogspot.in/2014/12/find-d repeatate-records-basing-on-any.html
CREATE TABLE tbl_master
(`id` int, `email` varchar(15));
INSERT INTO tbl_master
(`id`, `email`) VALUES
(1, 'test1@gmail.com'),
(2, 'test2@gmail.com'),
(3, 'test1@gmail.com'),
(4, 'test2@gmail.com'),
(5, 'test5@gmail.com');
QUERY : SELECT id, email FROM tbl_master
WHERE email IN (SELECT email FROM tbl_master GROUP BY email HAVING COUNT(id) > 1)
SELECT DISTINCT a.email FROM `users` a LEFT JOIN `users` b ON a.email = b.email WHERE a.id != b.id;
a.email
để a.*
và nhận được tất cả các ID của các hàng với các bản sao.
SELECT DISTINCT a.*
giải quyết gần như ngay lập tức.
Để xóa các hàng trùng lặp với nhiều trường, trước tiên, hủy chúng thành khóa duy nhất mới được chỉ định cho các hàng riêng biệt, sau đó sử dụng lệnh "group by" để xóa các hàng trùng lặp với cùng một khóa duy nhất mới:
Create TEMPORARY table tmp select concat(f1,f2) as cfs,t1.* from mytable as t1;
Create index x_tmp_cfs on tmp(cfs);
Create table unduptable select f1,f2,... from tmp group by cfs;
CREATE TEMPORARY TABLE ...
? Một lời giải thích nhỏ về giải pháp của bạn sẽ là tuyệt vời.
Một đóng góp rất muộn ... trong trường hợp nó giúp bất kỳ ai chờ đợi ... Tôi có nhiệm vụ tìm các cặp giao dịch phù hợp (thực sự là cả hai mặt của chuyển khoản từ tài khoản) trong một ứng dụng ngân hàng, để xác định giao dịch nào là 'từ' và 'đến' cho mỗi giao dịch chuyển tiền giữa các tài khoản, vì vậy chúng tôi đã kết thúc với điều này:
SELECT
LEAST(primaryid, secondaryid) AS transactionid1,
GREATEST(primaryid, secondaryid) AS transactionid2
FROM (
SELECT table1.transactionid AS primaryid,
table2.transactionid AS secondaryid
FROM financial_transactions table1
INNER JOIN financial_transactions table2
ON table1.accountid = table2.accountid
AND table1.transactionid <> table2.transactionid
AND table1.transactiondate = table2.transactiondate
AND table1.sourceref = table2.destinationref
AND table1.amount = (0 - table2.amount)
) AS DuplicateResultsTable
GROUP BY transactionid1
ORDER BY transactionid1;
Kết quả là các DuplicateResultsTable
hàng cung cấp các hàng chứa các giao dịch khớp (nghĩa là trùng lặp), nhưng nó cũng cung cấp cùng một id giao dịch ngược lại lần thứ hai khớp với cùng một cặp, do đó, bên ngoài SELECT
sẽ ở đó để nhóm theo ID giao dịch đầu tiên, được thực hiện bằng cách sử dụng LEAST
và GREATEST
để đảm bảo hai giao dịch luôn theo cùng một thứ tự trong kết quả, điều này làm cho nó an toàn với GROUP
lần đầu tiên, do đó loại bỏ tất cả các kết quả trùng lặp. Chạy qua gần một triệu hồ sơ và xác định hơn 12.000 trận đấu chỉ trong chưa đầy 2 giây. Tất nhiên, giao dịch là chỉ số chính, thực sự có ích.
Select column_name, column_name1,column_name2, count(1) as temp from table_name group by column_name having temp > 1
Nếu bạn muốn loại bỏ sử dụng trùng lặp DISTINCT
Nếu không, sử dụng truy vấn này:
SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;
Hãy thử sử dụng truy vấn này:
SELECT name, COUNT(*) value_count FROM company_master GROUP BY name HAVING value_count > 1;