Apa bedanya dari sudut pandang fungsi penghilangan duplikat belaka
Terlepas dari kenyataan bahwa tidak seperti DISTINCT
, GROUP BY
memungkinkan untuk mengumpulkan data per kelompok (yang telah disebutkan oleh banyak jawaban lain), perbedaan paling penting menurut saya adalah kenyataan bahwa dua operasi "terjadi" pada dua langkah yang sangat berbeda dalam urutan logis operasi yang dieksekusi dalam sebuah SELECT
pernyataan .
Berikut adalah operasi yang paling penting:
FROM
(termasuk JOIN
, APPLY
, dll)
WHERE
GROUP BY
(dapat menghapus duplikat)
- Agregasi
HAVING
- Fungsi jendela
SELECT
DISTINCT
(dapat menghapus duplikat)
UNION
, INTERSECT
, EXCEPT
(Dapat menghapus duplikat)
ORDER BY
OFFSET
LIMIT
Seperti yang Anda lihat, urutan logis dari setiap operasi memengaruhi apa yang dapat dilakukan dengannya dan bagaimana hal itu memengaruhi operasi berikutnya. Secara khusus, fakta bahwa GROUP BY
operasi "terjadi sebelum" yang SELECT
operasi (proyeksi) berarti bahwa:
- Itu tidak tergantung pada proyeksi (yang bisa menjadi keuntungan)
- Itu tidak dapat menggunakan nilai apa pun dari proyeksi (yang bisa merugikan)
1. Itu tidak tergantung pada proyeksi
Contoh di mana tidak tergantung pada proyeksi berguna adalah jika Anda ingin menghitung fungsi jendela pada nilai yang berbeda:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating
Ketika dijalankan terhadap basis data Sakila , ini menghasilkan:
rating rn
-----------
G 1
NC-17 2
PG 3
PG-13 4
R 5
Hal yang sama tidak dapat dicapai dengan DISTINCT
mudah:
SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
Kueri itu "salah" dan menghasilkan sesuatu seperti:
rating rn
------------
G 1
G 2
G 3
...
G 178
NC-17 179
NC-17 180
...
Ini bukan yang kita inginkan. The DISTINCT
Operasi "terjadi setelah" proyeksi, sehingga kita tidak lagi dapat menghapus DISTINCT
peringkat karena fungsi jendela sudah dihitung dan diproyeksikan. Untuk menggunakan DISTINCT
, kami harus membuat sarang bagian dari permintaan itu:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
SELECT DISTINCT rating FROM film
) f
Catatan: Dalam kasus khusus ini, kita juga bisa menggunakanDENSE_RANK()
SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film
2. Tidak dapat menggunakan nilai apa pun dari proyeksi
Salah satu kelemahan SQL adalah verbositasnya. Untuk alasan yang sama seperti apa yang telah kita lihat sebelumnya (yaitu urutan operasi logis), kita tidak dapat "dengan mudah" mengelompokkan berdasarkan sesuatu yang kita proyeksikan.
Ini adalah SQL yang tidak valid:
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name
Ini valid (mengulangi ungkapan)
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name
Ini juga berlaku (bersarang ekspresi)
SELECT name
FROM (
SELECT first_name || ' ' || last_name AS name
FROM customer
) c
GROUP BY name
Saya telah menulis tentang topik ini secara lebih mendalam dalam sebuah posting blog