Các ví dụ sau trả về các hàng trùng lặp từ bảng Cơ sở dữ liệu Oracle.
Dữ liệu Mẫu
Giả sử chúng ta có một bảng với dữ liệu sau:
SELECT * FROM Pets;
Kết quả:
PetId PetName PetType ----- ------- ------- 1 Wag Dog 1 Wag Dog 2 Scratch Cat 3 Tweet Bird 4 Bark Dog 4 Bark Dog 4 Bark Dog
Hai hàng đầu tiên trùng lặp, ba hàng cuối cùng cũng vậy. Trong trường hợp này, các hàng trùng lặp chứa các giá trị trùng lặp trên tất cả các cột, bao gồm cả cột ID.
Tùy chọn 1
Chúng ta có thể sử dụng truy vấn sau để xem có bao nhiêu hàng trùng lặp:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY PetId;
Kết quả:
PETID PETNAME PETTYPE Count 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1 4 Bark Dog 3
Chúng tôi đã nhóm các hàng theo tất cả các cột và trả về số hàng của mỗi nhóm. Bất kỳ hàng nào có số lượng lớn hơn 1 đều là hàng trùng lặp.
Chúng tôi có thể sắp xếp nó theo số lượng theo thứ tự giảm dần, để các hàng có nhiều bản sao nhất sẽ xuất hiện đầu tiên:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY Count(*) DESC;
Kết quả:
PETID PETNAME PETTYPE Count 4 Bark Dog 3 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1
Tùy chọn 2
Nếu chúng ta chỉ muốn các hàng trùng lặp được liệt kê, chúng ta có thể sử dụng HAVING
mệnh đề chỉ trả về các hàng có tổng số lớn hơn 1:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC;
Kết quả:
PETID PETNAME PETTYPE Count 4 Bark Dog 3 1 Wag Dog 2
Tùy chọn 3
Một tùy chọn khác là sử dụng ROW_NUMBER()
chức năng cửa sổ:
SELECT
PetId,
PetName,
PetType,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS rn
FROM Pets;
Kết quả:
PETID PETNAME PETTYPE RN 1 Wag Dog 1 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1 4 Bark Dog 1 4 Bark Dog 2 4 Bark Dog 3
PARTITION BY
mệnh đề chia tập kết quả được tạo ra bởi FROM
mệnh đề thành các phân vùng mà hàm được áp dụng. Khi chúng ta chỉ định phân vùng cho tập kết quả, mỗi phân vùng sẽ làm cho việc đánh số bắt đầu lại (tức là việc đánh số sẽ bắt đầu từ 1 cho hàng đầu tiên trong mỗi phân vùng).
Tùy chọn 4
Chúng ta có thể sử dụng truy vấn trên làm biểu thức bảng chung:
WITH cte AS
(
SELECT
PetId,
PetName,
PetType,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets
)
SELECT * FROM cte WHERE Row_Number <> 1;
Kết quả:
PETID PETNAME PETTYPE ROW_NUMBER 1 Wag Dog 2 4 Bark Dog 2 4 Bark Dog 3
Điều này chỉ trả về các hàng thừa từ các bản sao phù hợp. Vì vậy, nếu có hai hàng giống nhau, nó trả về một trong số chúng. Nếu có ba hàng giống nhau, nó trả về hai, v.v.
Tùy chọn 5
Do bảng của chúng tôi không chứa cột khóa chính, chúng tôi có thể tận dụng rowid
của Oracle cột giả:
SELECT * FROM Pets
WHERE EXISTS (
SELECT 1 FROM Pets p2
WHERE Pets.PetName = p2.PetName
AND Pets.PetType = p2.PetType
AND Pets.rowid > p2.rowid
);
Kết quả:
PETID PETNAME PETTYPE 1 Wag Dog 4 Bark Dog 4 Bark Dog
Cách hoạt động của điều này là, mỗi hàng trong cơ sở dữ liệu Oracle có một rowid
cột giả trả về địa chỉ của hàng. rowid
là mã định danh duy nhất cho các hàng trong bảng và thường giá trị của nó xác định duy nhất một hàng trong cơ sở dữ liệu. Tuy nhiên, điều quan trọng cần lưu ý là các hàng trong các bảng khác nhau được lưu trữ cùng nhau trong cùng một cụm có thể có cùng một rowid
.
Một lợi ích của ví dụ trên là chúng ta có thể thay thế SELECT *
với DELETE
để xóa mờ bảng.
Tùy chọn 6
Và cuối cùng, đây là một tùy chọn khác sử dụng rowid
cột giả:
SELECT * FROM Pets
WHERE rowid > (
SELECT MIN(rowid) FROM Pets p2
WHERE Pets.PetName = p2.PetName
AND Pets.PetType = p2.PetType
);
Kết quả:
PETID PETNAME PETTYPE 1 Wag Dog 4 Bark Dog 4 Bark Dog
Kết quả tương tự như ví dụ trước.
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 khỏi bảng.