ความแตกต่างจากมุมมองการทำงานของการลบแบบซ้ำซ้อนคืออะไร
นอกเหนือจากความเป็นจริงที่แตกต่างDISTINCT
, GROUP BY
ช่วยให้การรวมข้อมูลต่อกลุ่ม (ซึ่งได้รับการกล่าวถึงโดยคำตอบอื่น ๆ อีกมากมาย) ความแตกต่างที่สำคัญที่สุดในความคิดของฉันคือความจริงที่ว่าทั้งสองดำเนินการ "เกิดขึ้น" ที่สองขั้นตอนที่แตกต่างกันมากในลำดับที่เป็นตรรกะ ของการดำเนินงานที่มีการดำเนินการในSELECT
คำสั่ง
นี่คือการดำเนินการที่สำคัญที่สุด:
FROM
(รวมทั้งJOIN
, APPLY
ฯลฯ )
WHERE
GROUP BY
(สามารถลบรายการซ้ำได้)
- รวมตัว
HAVING
- ฟังก์ชั่นหน้าต่าง
SELECT
DISTINCT
(สามารถลบรายการซ้ำได้)
UNION
, INTERSECT
, EXCEPT
(สามารถลบข้อมูลที่ซ้ำกัน)
ORDER BY
OFFSET
LIMIT
อย่างที่คุณเห็นลำดับลอจิคัลของการดำเนินการแต่ละอย่างมีผลต่อสิ่งที่สามารถทำได้ โดยเฉพาะอย่างยิ่งความจริงที่ว่าการGROUP BY
ดำเนินการ"เกิดขึ้นก่อน"การSELECT
ดำเนินการ (ประมาณการ) หมายความว่า:
- มันไม่ได้ขึ้นอยู่กับการฉาย (ซึ่งอาจเป็นประโยชน์)
- ไม่สามารถใช้ค่าใด ๆ จากการฉายภาพ (ซึ่งอาจเป็นข้อเสีย)
1. มันไม่ได้ขึ้นอยู่กับการฉาย
ตัวอย่างที่ไม่ได้ขึ้นอยู่กับการฉายมีประโยชน์คือถ้าคุณต้องการคำนวณฟังก์ชั่นหน้าต่างในค่าที่แตกต่าง:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating
เมื่อทำงานกับฐานข้อมูล Sakilaผลตอบแทนนี้:
rating rn
-----------
G 1
NC-17 2
PG 3
PG-13 4
R 5
สิ่งเดียวกันนี้ไม่สามารถทำได้DISTINCT
อย่างง่ายดายด้วย:
SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
ข้อความค้นหานั้น "ผิด" และให้ผลเช่น:
rating rn
------------
G 1
G 2
G 3
...
G 178
NC-17 179
NC-17 180
...
นี่ไม่ใช่สิ่งที่เราต้องการ การDISTINCT
ดำเนินการ"เกิดขึ้นหลังจาก"การฉายภาพดังนั้นเราจึงไม่สามารถลบDISTINCT
คะแนนได้อีกเพราะฟังก์ชั่นหน้าต่างได้รับการคำนวณและคาดการณ์ไว้แล้ว ในการใช้งานDISTINCT
เราจะต้องซ้อนส่วนนั้นของแบบสอบถาม:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
SELECT DISTINCT rating FROM film
) f
หมายเหตุด้านข้าง: ในกรณีนี้เราสามารถใช้DENSE_RANK()
SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film
2. ไม่สามารถใช้ค่าใด ๆ จากการฉาย
หนึ่งในข้อเสียของ SQL คือความละเอียดฟุ้งซ่านในบางครั้ง ด้วยเหตุผลเดียวกับสิ่งที่เราเคยเห็นมาก่อน (เช่นลำดับตรรกะของการดำเนินงาน) เราไม่สามารถจัดกลุ่ม "ง่าย" โดยสิ่งที่เราคาดการณ์ไว้
นี่คือ SQL ที่ไม่ถูกต้อง:
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name
สิ่งนี้ใช้ได้ (การแสดงออกซ้ำ)
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name
สิ่งนี้ใช้ได้เช่นกัน (ซ้อนการแสดงออก)
SELECT name
FROM (
SELECT first_name || ' ' || last_name AS name
FROM customer
) c
GROUP BY name
ฉันได้เขียนเกี่ยวกับหัวข้อนี้ในเชิงลึกมากขึ้นในโพสต์บล็อก