Yalnızca yinelenen kaldırma işlevselliği açısından fark nedir
Bunun aksine DISTINCT
, grup başınaGROUP BY
verilerin toplanmasına izin verdiği gerçeğinin yanı sıra (diğer birçok cevapla belirtilmiştir), bence en önemli fark, iki işlemin mantıksal sırada iki farklı adımda "gerçekleşmesi" dir. ifadede yürütülen işlemlerin listesi .SELECT
İşte en önemli işlemler:
FROM
(dahil JOIN
, APPLY
vb)
WHERE
GROUP BY
(kopyaları kaldırabilir)
- toplamaları
HAVING
- Pencere fonksiyonları
SELECT
DISTINCT
(kopyaları kaldırabilir)
UNION
, INTERSECT
, EXCEPT
(Çiftleri kaldırabilir)
ORDER BY
OFFSET
LIMIT
Gördüğünüz gibi, her işlemin mantıksal sırası, onunla neler yapılabileceğini ve sonraki işlemleri nasıl etkilediğini etkiler. Özellikle, aslında o GROUP BY
operasyon "önce olur"SELECT
işlemi (projeksiyon) araçlarının:
- Projeksiyona bağlı değildir (bu bir avantaj olabilir)
- Projeksiyondaki hiçbir değeri kullanamaz (bu bir dezavantaj olabilir)
1. Bu projeksiyona bağlı değildir
Yansıtmaya bağlı olmamanın yararlı olduğu bir örnek, pencere işlevlerini farklı değerlerde hesaplamak istiyorsanız:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating
Sakila veritabanına karşı çalıştırıldığında , bu şu sonuçları verir:
rating rn
-----------
G 1
NC-17 2
PG 3
PG-13 4
R 5
Aynı şey DISTINCT
kolayca gerçekleştirilemedi:
SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
Bu sorgu "yanlış" ve aşağıdaki gibi bir sonuç veriyor:
rating rn
------------
G 1
G 2
G 3
...
G 178
NC-17 179
NC-17 180
...
İstediğimiz bu değil. DISTINCT
Operasyon "sonra olur" artık kaldırmak böylece, projeksiyon DISTINCT
pencere fonksiyonu zaten hesaplanmış ve yansıtılan çünkü derecelendirme. Kullanım için DISTINCT
, biz sorgu bir parçası olduğunu yuva olurdu:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
SELECT DISTINCT rating FROM film
) f
Yan not: Bu özel durumda,DENSE_RANK()
SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film
2. Projeksiyondaki hiçbir değeri kullanamaz
SQL'in dezavantajlarından biri, zaman zaman ayrıntı vermesidir. Daha önce gördüğümüzle aynı nedenden ötürü (yani mantıksal işlem sırası), yansıttığımız bir şeye göre "kolayca" gruplayamayız.
Bu geçersiz SQL:
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name
Bu geçerlidir (ifadeyi tekrarlamak)
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name
Bu da geçerlidir (ifadeyi iç içe yerleştirme)
SELECT name
FROM (
SELECT first_name || ' ' || last_name AS name
FROM customer
) c
GROUP BY name
Bu konu hakkında bir blog yazısında daha derinlemesine yazdım