PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

7 cách tìm hàng trùng lặp trong PostgreSQL khi bỏ qua khóa chính

Dưới đây là bảy cách để trả về các hàng trùng lặp trong PostgreSQL khi các hàng đó có khóa chính hoặc cột định danh duy nhất khác.

Điều này có nghĩa là các hàng trùng lặp chia sẻ chính xác các giá trị giống nhau trên tất cả các cột ngoại trừ khóa chính / cột ID duy nhất của chúng.

Dữ liệu mẫu

Chúng tôi sẽ sử dụng dữ liệu sau cho các ví dụ của chúng tôi:

SELECT * FROM Dogs;

Kết quả:

 dogid | firstname | lastname 
-------+-----------+----------
     1 | Bark      | Smith
     2 | Bark      | Smith
     3 | Woof      | Jones
     4 | Ruff      | Robinson
     5 | Wag       | Johnson
     6 | Wag       | Johnson
     7 | Wag       | Johnson

Hai hàng đầu tiên trùng lặp (ngoại trừ DogId , là khóa chính của bảng và chứa một giá trị duy nhất trên tất cả các hàng). Ba hàng cuối cùng cũng trùng lặp (ngoại trừ DogId cột).

Cột khóa chính đảm bảo rằng không có hàng trùng lặp, đây là phương pháp hay trong RDBMS, vì khóa chính giúp thực thi tính toàn vẹn của dữ liệu. Nhưng vì khóa chính ngăn các hàng trùng lặp, chúng có khả năng cản trở khả năng tìm thấy các hàng trùng lặp của chúng tôi.

Trong bảng của chúng tôi ở trên, cột khóa chính là một số tăng dần và giá trị của nó không mang ý nghĩa và không quan trọng. Do đó, chúng ta cần bỏ qua hàng đó nếu chúng ta muốn tìm các bản sao trong các cột khác.

Tùy chọn 1

Chúng ta có thể sử dụng SQL GROUP BY mệnh đề để nhóm các cột theo các cột quan trọng của chúng, sau đó sử dụng COUNT() hàm trả về số lượng hàng giống nhau:

SELECT 
    FirstName, 
    LastName, 
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName;

Kết quả:

 firstname | lastname | count 
-----------+----------+-------
 Ruff      | Robinson |     1
 Wag       | Johnson  |     3
 Woof      | Jones    |     1
 Bark      | Smith    |     2

Ở đây, chúng tôi đã loại trừ cột khóa chính bằng cách bỏ qua cột đó khỏi truy vấn của chúng tôi.

Kết quả cho chúng ta biết rằng có ba hàng chứa Wag Johnson và hai hàng chứa Bark Smith. Đây là các bản sao (hoặc bản sao ba bản trong trường hợp của Wag Johnson). Hai hàng còn lại không có bất kỳ bản sao nào.

Tùy chọn 2

Chúng tôi có thể loại trừ các trường hợp không trùng lặp khỏi đầu ra bằng HAVING mệnh đề:

SELECT 
    FirstName, 
    LastName, 
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
HAVING COUNT(*) > 1;

Kết quả:

 firstname | lastname | count 
-----------+----------+-------
 Wag       | Johnson  |     3
 Bark      | Smith    |     2

Tùy chọn 3

Dưới đây là một ví dụ về việc kiểm tra các bản sao trên các cột được nối. Trong trường hợp này, chúng tôi sử dụng CONCAT() để nối hai cột của chúng ta, sử dụng DISTINCT từ khóa để nhận các giá trị riêng biệt, sau đó sử dụng COUNT() hàm để trả về số lượng:

SELECT
    DISTINCT CONCAT(FirstName, ' ', LastName) AS DogName,
    COUNT(*) AS Count
FROM Dogs
GROUP BY CONCAT(FirstName, ' ', LastName);

Kết quả:

    dogname    | count 
---------------+-------
 Wag Johnson   |     3
 Ruff Robinson |     1
 Woof Jones    |     1
 Bark Smith    |     2

Tùy chọn 4

Ngoài ra, chúng tôi có thể sử dụng ROW_NUMBER() chức năng cửa sổ:

SELECT 
    *,
    ROW_NUMBER() OVER ( 
        PARTITION BY FirstName, LastName 
        ORDER BY FirstName, LastName
        ) AS Row_Number
FROM Dogs;

Kết quả:

 dogid | firstname | lastname | row_number 
-------+-----------+----------+------------
     1 | Bark      | Smith    |          1
     2 | Bark      | Smith    |          2
     4 | Ruff      | Robinson |          1
     5 | Wag       | Johnson  |          1
     6 | Wag       | Johnson  |          2
     7 | Wag       | Johnson  |          3
     3 | Woof      | Jones    |          1

Sử dụng PARTITION mệnh đề dẫn đến một cột mới được thêm vào, với số hàng tăng lên mỗi khi có một bản sao, nhưng đặt lại lần nữa khi có một hàng duy nhất.

Trong trường hợp này, chúng tôi không nhóm các kết quả, có nghĩa là chúng tôi có thể thấy từng hàng trùng lặp, bao gồm cả cột định danh duy nhất của nó.

Tùy chọn 5

Chúng ta cũng có thể sử dụng ví dụ trước làm biểu thức bảng chung trong một truy vấn lớn hơn:

WITH cte AS 
    (
        SELECT 
            *,
            ROW_NUMBER() OVER ( 
                PARTITION BY FirstName, LastName 
                ORDER BY FirstName, LastName
                ) AS Row_Number
        FROM Dogs
    )
SELECT * FROM cte WHERE Row_Number <> 1;

Kết quả:

 dogid | firstname | lastname | row_number 
-------+-----------+----------+------------
     2 | Bark      | Smith    |          2
     6 | Wag       | Johnson  |          2
     7 | Wag       | Johnson  |          3

Điều này loại trừ các bản không trùng lặp khỏi đầu ra và nó loại trừ một hàng của mỗi bản sao khỏi đầu ra. Nói cách khác, nó chỉ hiển thị các hàng thừa từ các bản sao. Các hàng này là ứng cử viên chính để bị xóa trong một hoạt động gỡ bỏ.

Tùy chọn 6

Dưới đây là một cách ngắn gọn hơn để có được kết quả giống như ví dụ trước:

SELECT * FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    EXCEPT SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    );

Kết quả:

 dogid | firstname | lastname 
-------+-----------+----------
     6 | Wag       | Johnson
     2 | Bark      | Smith
     7 | Wag       | Johnson

Một điểm khác biệt giữa ví dụ này và ví dụ trước là ví dụ này không yêu cầu tạo số hàng riêng biệt của chúng ta.

Tùy chọn 7

Đây là một tùy chọn khác để trả về các hàng trùng lặp trong Postgres:

SELECT * 
FROM Dogs d1, Dogs d2 
WHERE d1.FirstName = d2.FirstName 
AND d1.LastName = d2.LastName
AND d1.DogId <> d2.DogId 
AND d1.DogId = (
    SELECT MAX(DogId) 
    FROM Dogs d3 
    WHERE d3.FirstName = d1.FirstName 
    AND d3.LastName = d1.LastName
);

Kết quả:

 dogid | firstname | lastname | dogid | firstname | lastname 
-------+-----------+----------+-------+-----------+----------
     2 | Bark      | Smith    |     1 | Bark      | Smith
     7 | Wag       | Johnson  |     5 | Wag       | Johnson
     7 | Wag       | Johnson  |     6 | Wag       | Johnson

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Trả về bảng động với các cột không xác định từ hàm PL / pgSQL

  2. ngủ đông không thể nhận giá trị trình tự tiếp theo

  3. 8 tính năng tương thích mới của Oracle trong EnterpriseDB PPAS 9.2 Beta

  4. ECONNREFUSED cho Postgres trên nodeJS với dockers

  5. Làm thế nào để loại bỏ cơ sở dữ liệu PostgreSQL nếu có các kết nối đang hoạt động với nó?