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

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

Dưới đây là mười một tùy chọn để trả về các hàng trùng lặp trong SQLite khi các hàng đó có khóa chính hoặc một số cột định danh duy nhất khác (nhưng bạn muốn bỏ qua khóa chính).

Đ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 Robinson5 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 nên 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 có ý 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 tôi có thể chạy một truy vấn với GROUP BY để 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
ORDER BY Count DESC; 

Kết quả:

 FirstName LastName Count --------- -------- ----- Wag Johnson 3 Bark Smith 2 Ruff Robinson 1 Woof Jones 1 

Ở đâ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. Chúng tôi cũng đã sắp xếp nó theo số lượng theo thứ tự giảm dần để các bản sao xuất hiện đầu tiên.

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 ta có thể sử dụng HAVING mệnh đề loại trừ các bản không trùng lặp khỏi đầu ra:

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

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 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 FirstName || ' ' || LastName AS DogName,
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName || ' ' || LastName
ORDER BY Count DESC; 

Kết quả:

 DogName Count ------------- ----- Wag Johnson 3 Bark Smith 2 Woof Jones 1 Ruff Robinson 1 

Tùy chọn 4

Theo mặc định, mỗi hàng trong SQLite có một cột đặc biệt, thường được gọi là rowid , xác định duy nhất hàng đó trong bảng. Trừ khi nó đã bị xóa rõ ràng khỏi bảng, bạn có thể sử dụng nó làm số nhận dạng duy nhất cho mỗi hàng.

Do đó, chúng tôi có thể sử dụng rowid trong truy vấn của chúng tôi:

 SELECT * FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.rowid > d2.rowid
); 

Kết quả:

 DogId FirstName LastName ----- --------- -------- 2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Chúng tôi có thể thay thế SELECT * với DELETE để thực hiện thao tác khử trùng lặp trên bảng.

Lưu ý rằng chúng tôi có thể đã sử dụng DogId cột (khóa chính của chúng tôi) thay vì rowid nếu chúng tôi muốn. Điều đó nói rằng, rowid có thể hữu ích nếu bạn không thể sử dụng cột khóa chính vì lý do nào đó hoặc nếu bảng không có khóa chính.

Tùy chọn 5

Đây là một truy vấn khác sử dụng rowid :

 SELECT * FROM Dogs
WHERE rowid > (
  SELECT MIN(rowid) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
); 

Kết quả:

 DogId FirstName LastName ----- --------- -------- 2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Như với ví dụ trước, chúng ta có thể thay thế SELECT * với DELETE để xóa các hàng trùng lặp.

Tùy chọn 6

Hai rowid các tùy chọn ở trên là rất tốt nếu bạn phải hoàn toàn bỏ qua khóa chính trong truy vấn của mình (hoặc nếu bạn hoàn toàn không có cột khóa chính). Tuy nhiên, như đã đề cập, vẫn có tùy chọn thay thế rowid với cột khóa chính - trong trường hợp của chúng tôi là DogId cột:

 SELECT * FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.DogId > d2.DogId
); 

Kết quả:

 DogId FirstName LastName ----- --------- -------- 2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Tùy chọn 7

Và đây là truy vấn khác với rowid được thay thế bằng DogId cột:

 SELECT * FROM Dogs
WHERE DogId > (
  SELECT MIN(DogId) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
); 

Kết quả:

 DogId FirstName LastName ----- --------- -------- 2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Tùy chọn 8

Một cách khác để làm điều đó là 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 9

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 đó 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.

Tùy chọn 10

Đây là một cách khác để có được đầu ra 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 ----- --------- -------- 2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Tùy chọn 11

Dưới đây là một tùy chọn khác để chọn các bản sao từ bảng của chúng tôi:

 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. Cách lấy một hàng trong SQLite theo chỉ mục (không phải theo id)

  2. Ngoại lệ SQLite trong khi cố gắng xóa hàng

  3. Khóa ngoại SQLite

  4. Nhập tệp CSV vào bảng SQLite

  5. Cách Group_Concat () hoạt động trong SQLite