Làm cách nào để tìm các giá trị trùng lặp trong một bảng trong Oracle?


276

Câu lệnh SQL đơn giản nhất sẽ trả về các giá trị trùng lặp cho một cột đã cho và số lần xuất hiện của chúng trong bảng cơ sở dữ liệu Oracle là gì?

Ví dụ: Tôi có một JOBSbảng với cột JOB_NUMBER. Làm cách nào tôi có thể biết mình có bất kỳ bản sao nào JOB_NUMBERkhông và chúng được nhân đôi bao nhiêu lần?


1
các giải pháp khác stackoverflow.com/questions/4522431/
Mạnh

Câu trả lời:


608
SELECT column_name, COUNT(column_name)
FROM table_name
GROUP BY column_name
HAVING COUNT(column_name) > 1;

1
Cảm ơn - đó là câu trả lời tôi vừa tìm thấy và bạn đánh bại tôi để đăng nó trở lại đây! : o)
Andrew

3
Không có gì. Bây giờ tôi sắp đăng câu hỏi của riêng mình về sự khác biệt giữa đếm (cột) và đếm (*). :)
Bill the Lizard

44
+1 hơn 4 năm sau, vẫn hoạt động tốt và có thể được điều chỉnh để chọn nhiều cột miễn là các cột đó cũng group bynhư trong: select column_one, column_two, count(*) from tablename group by column_one, column_two having count(column_one) > 1;v.v.
Amos M. Carpenter

4
hoặc thậm chí having count(*) > 1: D
Stanislav Mamontov

3
+1 hơn 8 năm sau, vẫn hoạt động tốt cho cả hai phiên bản mới nhất của Oracle và MySQL (loại bỏ không gian sau khi chức năng đếm có dòng).
PhatHV

58

Cách khác:

SELECT *
FROM TABLE A
WHERE EXISTS (
  SELECT 1 FROM TABLE
  WHERE COLUMN_NAME = A.COLUMN_NAME
  AND ROWID < A.ROWID
)

Hoạt động tốt (đủ nhanh) khi có chỉ số trên column_name. Và đó là cách tốt hơn để xóa hoặc cập nhật các hàng trùng lặp.


3
+1 hoạt động tốt đối với các mục trùng lặp nhiều cột (ví dụ: khi bạn muốn thêm ràng buộc UNIITE trên một số cột), tôi thấy cách tiếp cận này ít "cứng nhắc" hơn so với NHÓM THEO để liệt kê các giá trị trường trùng lặp + các trường khác nếu cần.
Frosty Z

3
Chỉ cần làm rõ, lúc đầu tôi không rõ ràng) truy vấn này chỉ trả về các bản sao, nó không trả về mục nhập ban đầu đầu tiên, đó là lý do tại sao nó hoạt động tốt để xóa các bản sao, dựa trên một ràng buộc duy nhất trên nhiều hơn 1 cột. Bạn có thể chọn các ID trùng lặp với truy vấn này và sau đó sử dụng các ID đó để xóa các bản sao.
matthewb

1
nếu bạn thay đổi <thành! = bạn sẽ nhận được tất cả các bản ghi trùng lặp. không chỉ là kỷ lục thứ 2 hoặc thứ 3
moore1emu

33

Đơn giản nhất tôi có thể nghĩ về:

select job_number, count(*)
from jobs
group by job_number
having count(*) > 1;

1
Làm thế nào tôi có thể nhận được tất cả các cột?
Asif Mushtaq

2
chọn * từ các công việc có job_number trong (chọn job_number từ nhóm công việc theo job_number có số đếm (*)> 1)
JosephStyons

17

Bạn thậm chí không cần phải có số đếm trong các cột được trả về nếu bạn không cần biết số lượng trùng lặp thực tế. ví dụ

SELECT column_name
FROM table
GROUP BY column_name
HAVING COUNT(*) > 1

7

Làm thế nào về:

SELECT <column>, count(*)
FROM <table>
GROUP BY <column> HAVING COUNT(*) > 1;

Để trả lời ví dụ trên, nó sẽ giống như:

SELECT job_number, count(*)
FROM jobs
GROUP BY job_number HAVING COUNT(*) > 1;

5

Trong trường hợp nhiều cột xác định hàng duy nhất (ví dụ: bảng quan hệ), bạn có thể sử dụng theo sau

Sử dụng id hàng, ví dụ emp_dept (empid, deptid, startdate, enddate) giả sử empid và deptid là duy nhất và xác định hàng trong trường hợp đó

select oed.empid, count(oed.empid) 
from emp_dept oed 
where exists ( select * 
               from  emp_dept ied 
                where oed.rowid <> ied.rowid and 
                       ied.empid = oed.empid and 
                      ied.deptid = oed.deptid )  
        group by oed.empid having count(oed.empid) > 1 order by count(oed.empid);

và nếu bảng như vậy có khóa chính thì hãy sử dụng khóa chính thay vì rowid, ví dụ id là pk thì

select oed.empid, count(oed.empid) 
from emp_dept oed 
where exists ( select * 
               from  emp_dept ied 
                where oed.id <> ied.id and 
                       ied.empid = oed.empid and 
                      ied.deptid = oed.deptid )  
        group by oed.empid having count(oed.empid) > 1 order by count(oed.empid);

4

Đang làm

select count(j1.job_number), j1.job_number, j1.id, j2.id
from   jobs j1 join jobs j2 on (j1.job_numer = j2.job_number)
where  j1.id != j2.id
group by j1.job_number

sẽ cung cấp cho bạn id của các hàng trùng lặp.


4
SELECT   SocialSecurity_Number, Count(*) no_of_rows
FROM     SocialSecurity 
GROUP BY SocialSecurity_Number
HAVING   Count(*) > 1
Order by Count(*) desc 

2

Tôi thường sử dụng hàm Phân tích Oracle ROW_NUMBER () .

Giả sử bạn muốn kiểm tra các bản sao bạn có liên quan đến một chỉ số duy nhất hoặc khóa chính được xây dựng trên các cột ( c1, c2, c3). Sau đó, bạn sẽ đi theo con đường này, đưa lên ROWIDs hàng trong đó số lượng dòng được mang theo ROW_NUMBER()>1:

Select * From Table_With_Duplicates
      Where Rowid In
                    (Select Rowid
                       From (Select Rowid,
                                    ROW_NUMBER() Over (
                                            Partition By c1 || c2 || c3
                                            Order By c1 || c2 || c3
                                        ) nbLines
                               From Table_With_Duplicates) t2
                      Where nbLines > 1)

1

Đây là một yêu cầu SQL để làm điều đó:

select column_name, count(1)
from table
group by column_name
having count (column_name) > 1;

1

Tôi biết một chủ đề cũ của nó nhưng điều này có thể giúp một số người.

Nếu bạn cần in các cột khác của bảng trong khi kiểm tra trùng lặp, hãy sử dụng bên dưới:

select * from table where column_name in
(select ing.column_name from table ing group by ing.column_name having count(*) > 1)
order by column_name desc;

cũng có thể thêm một số bộ lọc bổ sung trong mệnh đề where nếu cần.


0

1. giải pháp

select * from emp
    where rowid not in
    (select max(rowid) from emp group by empno);

Poster gốc này không bao giờ đề cập đến việc xóa, chỉ tính
Jeff

-1

Ngoài ra, bạn có thể thử một cái gì đó như thế này để liệt kê tất cả các giá trị trùng lặp trong bảng nói reqitem

SELECT count(poid) 
FROM poitem 
WHERE poid = 50 
AND rownum < any (SELECT count(*)  FROM poitem WHERE poid = 50) 
GROUP BY poid 
MINUS
SELECT count(poid) 
FROM poitem 
WHERE poid in (50)
GROUP BY poid 
HAVING count(poid) > 1;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.