Sự khác biệt từ quan điểm chức năng loại bỏ trùng lặp đơn thuần là gì
Ngoài thực tế là không giống như DISTINCT
, GROUP BY
cho phép tổng hợp dữ liệu cho mỗi nhóm (đã được đề cập bởi nhiều câu trả lời khác), sự khác biệt quan trọng nhất trong quan điểm của tôi là thực tế là hai thao tác "xảy ra" ở hai bước rất khác nhau theo thứ tự logic của các hoạt động được thực hiện trong một SELECT
tuyên bố .
Dưới đây là các hoạt động quan trọng nhất:
FROM
(bao gồm JOIN
, APPLY
, vv)
WHERE
GROUP BY
(có thể loại bỏ trùng lặp)
- Tập hợp
HAVING
- Chức năng cửa sổ
SELECT
DISTINCT
(có thể loại bỏ trùng lặp)
UNION
, INTERSECT
, EXCEPT
(Có thể loại bỏ bản sao)
ORDER BY
OFFSET
LIMIT
Như bạn có thể thấy, thứ tự logic của từng hoạt động ảnh hưởng đến những gì có thể được thực hiện với nó và cách nó ảnh hưởng đến các hoạt động tiếp theo. Đặc biệt, thực tế là các GROUP BY
hoạt động "xảy ra trước khi" các SELECT
hoạt động (chiếu) có nghĩa là:
- Nó không phụ thuộc vào phép chiếu (có thể là một lợi thế)
- Nó không thể sử dụng bất kỳ giá trị nào từ phép chiếu (có thể là một bất lợi)
1. Nó không phụ thuộc vào hình chiếu
Một ví dụ không phụ thuộc vào phép chiếu là hữu ích nếu bạn muốn tính các hàm cửa sổ trên các giá trị riêng biệt:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating
Khi chạy với cơ sở dữ liệu Sakila , điều này mang lại:
rating rn
-----------
G 1
NC-17 2
PG 3
PG-13 4
R 5
Điều tương tự không thể đạt được DISTINCT
một cách dễ dàng:
SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
Truy vấn đó là "sai" và mang lại một cái gì đó như:
rating rn
------------
G 1
G 2
G 3
...
G 178
NC-17 179
NC-17 180
...
Đây không phải là những gì chúng ta muốn. Các DISTINCT
hoạt động "xảy ra sau khi" chiếu, vì vậy chúng tôi không còn có thể loại bỏ DISTINCT
xếp hạng bởi vì chức năng cửa sổ đã được tính toán và dự báo. Để sử dụng DISTINCT
, chúng ta phải lồng một phần của truy vấn:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
SELECT DISTINCT rating FROM film
) f
Lưu ý phụ: Trong trường hợp cụ thể này, chúng tôi cũng có thể sử dụngDENSE_RANK()
SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film
2. Nó không thể sử dụng bất kỳ giá trị nào từ phép chiếu
Một trong những nhược điểm của SQL là tính dài dòng của nó. Vì lý do tương tự như những gì chúng ta đã thấy trước đây (cụ thể là thứ tự logic của các hoạt động), chúng ta không thể "dễ dàng" nhóm theo thứ gì đó chúng ta đang chiếu.
Đây là SQL không hợp lệ:
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name
Điều này là hợp lệ (lặp lại biểu thức)
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name
Điều này cũng hợp lệ (lồng biểu thức)
SELECT name
FROM (
SELECT first_name || ' ' || last_name AS name
FROM customer
) c
GROUP BY name
Tôi đã viết về chủ đề này sâu hơn trong một bài đăng trên blog