ทำไม NULL จึงถูกเรียงลำดับก่อน


20

ทำไมเมื่อเรามีค่า NULL ในคอลัมน์และเราเรียงตามค่าจากน้อยไปมาก NULL จะถูกเรียงลำดับก่อน

select 1 as test
union all
select 2
union all
select NULL
union all
select 3
union all
select 4
order by test

ผลลัพธ์ใน

NULL
1
2
3
4

ฉันคิดว่า NULL หมายถึง "ไม่ทราบแน่ชัด" หรือเป็นไปได้ "ไม่ทราบ" หากเป็นจริงพวกเขาจะไม่เรียงลำดับล่าสุดเนื่องจากค่าอาจมากกว่าค่าอื่น ๆ ทั้งหมดหรือไม่ (หรือนี่เป็นตัวเลือกการจัดเรียงที่อื่น)

ฉันใช้ SQL Server 2008R2 แต่ฉันสงสัยว่านี่เป็นความจริงในทุกเซิร์ฟเวอร์ SQL และอาจเป็นไปได้ใน RDBMS ทั้งหมด


1
Oracle แสดงรายการล่าสุด นั่นทำให้ฉันสับสนขึ้นหนึ่งครั้งโดยเชื่อว่ามันควรทำตัวเหมือน SQL Server
Andrei Rînea

2
"หากเป็นจริงพวกเขาจะไม่เรียงลำดับล่าสุดเนื่องจากค่าอาจมากกว่าค่าอื่น ๆ ทั้งหมด" ค่าอาจน้อยกว่าค่าอื่น ๆ ทั้งหมดเช่นกัน สำหรับฉันแล้วมันเป็นเรื่องง่ายที่ค่า falsey เช่น null ควรอยู่ด้านล่างสุด และในทางปฏิบัติเนื่องจากในทางปฏิบัติบ่อยครั้งที่คุณต้องการใช้การdescสั่งซื้อเพื่อแสดงสิ่งที่ยิ่งใหญ่ที่สุดหรือล่าสุดซึ่งในกรณีนี้ฉันยินดีที่จะให้สิ่งที่ไม่สิ้นสุด
mahemoff

ฐานข้อมูลทำในสิ่งที่คุณบอกให้ทำ หากคุณรู้ว่าข้อมูลของคุณมีโมฆะและคุณมีเหตุผลทางธุรกิจบางอย่างสำหรับการเรียงลำดับข้อมูลในลักษณะที่แน่นอนคุณจะต้องระบุว่าในแบบสอบถามหรือรหัส / มุมมองที่ประมวลผล / แสดงข้อมูล อย่าทิ้งการเรียงลำดับตามพฤติกรรมฐานข้อมูลเริ่มต้น
nothingisnecessary

คำตอบ:


19

BOL : ค่า NULL บ่งชี้ว่าไม่ทราบค่า ค่า NULL แตกต่างจากค่าว่างหรือศูนย์ ไม่มีค่า null สองค่าเท่ากัน เปรียบเทียบระหว่างค่า Null สองค่าหรือระหว่าง NULL กับค่าอื่น ๆ ส่งคืนค่าที่ไม่รู้จักเนื่องจากค่าของ NULL แต่ละค่าไม่เป็นที่รู้จัก

NULL หมายถึงไม่ทราบ ไม่มีการตีความอื่น ๆ ที่ถูกต้อง

หากเป็นจริงพวกเขาจะไม่เรียงลำดับล่าสุดเนื่องจากค่าอาจมากกว่าค่าอื่น ๆ ทั้งหมดหรือไม่

ไม่มีอาจเป็นได้ ไม่มีคือศักยภาพคุ้มค่า ไม่ทราบไม่ทราบไม่ทราบไม่ทราบ

สำหรับสาเหตุที่ปรากฏขึ้นเป็นครั้งแรกแทนที่จะเป็นครั้งสุดท้ายสิ่งนี้ไม่ได้รับการจัดทำขึ้นโดยมาตรฐาน SQL ที่เผยแพร่และน่าเสียดายที่ต้องพิจารณาตามดุลยพินิจของผู้จำหน่าย RDBMS:

Wikipedia : มาตรฐาน SQL ไม่ได้กำหนดลำดับการจัดเรียงเริ่มต้นสำหรับ Nulls อย่างชัดเจน บนระบบที่สอดคล้องกัน Nulls สามารถเรียงลำดับก่อนหรือหลังค่าข้อมูลทั้งหมดโดยใช้ NULLS FIRST หรือ NULLS LAST clauses อันดับแรกของรายการ ORDER BY ตามลำดับ ผู้ขาย DBMS บางรายไม่สามารถใช้ฟังก์ชันนี้ได้ ผู้ขายที่ไม่ได้ใช้ฟังก์ชั่นนี้อาจระบุวิธีการที่แตกต่างกันสำหรับการเรียงลำดับ Null ใน DBMS


ดังนั้นมันจึงเป็นการเรียกการตัดสิน นั่นทำให้รู้สึกมาก ขอบคุณ!
Richard

6

คุณถูกต้องซึ่งNULLอาจหมายถึง 'ไม่ทราบแน่ชัด' หรือ 'Uknownn' หรือ 'ยังไม่ทราบ' หรือ 'ไม่ใช้' แต่ไม่มีเหตุผลที่จะทำให้ Nulls เป็นคนแรกหรือคนสุดท้าย หากเราไม่ทราบค่าจริงแล้ว tehy อาจจะเล็กหรือใหญ่ก็ได้

ฉันคิดว่ามาตรฐานสำหรับกำหนดพฤติกรรมที่ต้องการของ Nulls ระหว่างการเรียงลำดับคือ:

ORDER BY 
    test NULLS LAST                      --- or NULLS FIRST for the opposite

น่าเสียดายที่ SQL-Server ยังไม่ได้ใช้ไวยากรณ์นี้ ถ้าฉันไม่ผิด PostgreSQL และ Oracle มีมัน

ทางออกหนึ่ง:

ORDER BY 
     CASE WHEN test IS NOT NULL 
            THEN 0 
          ELSE 1 
     END 
   , test

โซลูชันอื่นที่ต้องการการปรับตามประเภทข้อมูล - แต่จะไม่ preform อย่างดีเนื่องจากไม่สามารถใช้ดัชนีใน(test):

ORDER BY 
    COALESCE(test, 2147483647)               --- if it's a 4-byte signed integer

ด้วยวิธีนี้ ORDER BY COALESCE (ทดสอบ, 2147483647) เซิร์ฟเวอร์ SQL ไม่สามารถใช้ดัชนีได้
Ardalan Shahgholi

3

ฉันไม่รู้ว่าทำไมมันถึงทำแบบนั้น แต่โดยนิยาม NULLS ไม่สามารถเปรียบเทียบกับผู้ที่ไม่ใช่ NULLS ดังนั้นพวกเขาจึงต้องเริ่มต้นหรือสิ้นสุด (คำตอบของ Mark ครอบคลุมในรายละเอียดมากขึ้น)

เพื่อให้ได้พฤติกรรมที่คุณต้องการ - เท่าที่ฉันรู้ว่าไม่มีตัวเลือกการเรียงลำดับที่จะทำให้เป็นโมฆะดังนั้นคุณต้องหลบมันโดยใช้คอลัมน์ที่คำนวณเพื่อบังคับให้พวกมันอยู่ อย่างไรก็ตามใน SQL Server คุณไม่สามารถสั่งซื้อโดยคอลัมน์ที่คำนวณได้ ( CASE WHEN ...) เมื่อข้อมูลของคุณมีตัวดำเนินการชุด ( UNION ALL) ดังนั้น:

CREATE TABLE #sorttest(test int)
INSERT INTO #sorttest values(1)
INSERT INTO #sorttest values(5)
INSERT INTO #sorttest values(4)
INSERT INTO #sorttest values(NULL)
INSERT INTO #sorttest values(3)
INSERT INTO #sorttest values(2)
SELECT test
FROM #sorttest
ORDER BY CASE WHEN test IS NULL THEN 1 ELSE 0 END, test

DROP TABLE #sorttest

จะใช้งานได้สำหรับการเรียงลำดับ nulls ล่าสุด หากคุณต้องใช้UNION(หรือEXCEPTหรือINTERSECTS) เพื่อสร้างชุดข้อมูลของคุณให้ถ่ายโอนข้อมูลของคุณไปยังตารางชั่วคราวดังกล่าวข้างต้น


... หรือใช้เอาต์พุต UNIONed เป็นตารางที่ได้รับ
Andriy M

0

หากคุณกำลังติดต่อกับตัวเลขคุณสามารถใช้

ORDER BY -test DESC

NULLเป็นค่าต่ำสุดที่เป็นไปได้ดังนั้นDESCวางไว้ที่จุดสิ้นสุด ในขณะที่ค่าไม่เป็นโมฆะก็มีการกลับด้านดังนั้นDESCจริง ๆ แล้วเป็นASCค่าจริง ควรจะเร็วกว่าCASEและฉันคิดว่าเครื่องมือเพิ่มประสิทธิภาพคิวรีสามารถใช้ดัชนีในtestคอลัมน์ได้


3
ไม่มันไม่สามารถใช้ดัชนีสำหรับการเรียงลำดับได้ (- test)ถ้าคุณมีดัชนีในการแสดงออกคำนวณ
ypercubeᵀᴹ

1
ฉลาดแม้ว่าจะ จำกัด เฉพาะข้อมูลที่เป็นตัวเลขเท่านั้น (เหมาะสำหรับตัวอย่างของ OP แล้ว) ฉันไม่แน่ใจว่าสิ่งนี้จะเร็วกว่าการใช้ CASE หรือไม่ แต่ฉันแน่ใจว่ามันจะไม่ใช้ดัชนี (เว้นแต่จะเป็นสิ่งที่ @ ypercubeᵀᴹพูดว่า - แต่จากนั้นนิพจน์ CASE จะได้รับการจัดทำดัชนีในลักษณะเดียวกัน)
Andriy M
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.