MySQL เรียงลำดับตามจำนวน Nulls


280

ขณะนี้ฉันกำลังทำ OrderBy พื้นฐานมากในคำสั่งของฉัน

SELECT * FROM tablename WHERE visible=1 ORDER BY position ASC, id DESC

ปัญหานี้คือรายการ NULL สำหรับ 'ตำแหน่ง' ถือว่าเป็น 0 ดังนั้นรายการทั้งหมดที่มีตำแหน่งเป็น NULL จะปรากฏก่อนหน้ารายการที่มี 1,2,3,4 เช่น:

NULL, NULL, NULL, 1, 2, 3, 4

มีวิธีการสั่งซื้อดังต่อไปนี้:

1, 2, 3, 4, NULL, NULL, NULL.

8
คุณควรพิจารณาคำตอบของ user1052645 อีกครั้ง มันง่ายกว่าไม่จำเป็นต้องมีความรู้เกี่ยวกับค่าสูงสุดและอาจเร็วกว่า (การประเมินการแสดงออกอาจเร็วกว่าการเรียกใช้ฟังก์ชัน)
Steve Clay

คำตอบ:


568

MySQL มีไวยากรณ์ที่ไม่มีเอกสารเพื่อเรียงลำดับโมฆะสุดท้าย วางเครื่องหมายลบ (-) หน้าชื่อคอลัมน์และสลับ ASC เป็น DESC:

SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC, id DESC

มันเป็นหลักผกผันของposition DESCการวางค่า NULL สุดท้าย position ASCแต่อย่างอื่นเช่นเดียวกับ

การอ้างอิงที่ดีอยู่ที่นี่http://troels.arvin.dk/db/rdbms#select-order_by


79
มันไม่ได้ไม่มีเอกสาร- col_nameเป็นนิพจน์ ( 0 - col_name) ซึ่งข้อ ORDER BY ยอมรับ แน่นอนว่าใช้ได้กับคอลัมน์ตัวเลขเท่านั้น
Steve Clay

7
ทำได้ดีนี่. ทำงานสำหรับdateและtimeคอลัมน์ด้วย! (MySQL 5.5) ฉันเดา (ฉันขี้เกียจที่จะตรวจสอบ) มันใช้ได้กับคอลัมน์ที่มีลักษณะเหมือนจำนวนทั้งหมด (เวลาประทับลอย ... )
Martin

6
@koral: มันเป็นนิพจน์ทางคณิตศาสตร์ที่ง่าย (และมีประโยชน์) ที่กลับคำสั่งมันจะไม่ถูกลบออกนอกเสียจากว่าภาษาจะเปลี่ยนแปลงไปอย่างมาก
เบลล์

11
ตามความคิดเห็นที่แนะนำมันใช้กับคอลัมน์ตัวเลขวันที่และเวลาได้หรือไม่ แต่แล้ว varchar ล่ะ? สามารถใช้กับ varchar ได้หรือไม่? ฉันลองใช้กับฟิลด์ varchar แต่ดูเหมือนว่าคำสั่งจะแตกต่างจากการใช้ ASC หรือ DESC
Sumit Desai

9
สิ่งนี้จะป้องกันการใช้ดัชนีที่เป็นไปได้ในการเรียงลำดับตามคอลัมน์หรือไม่
Tarsis

306

ฉันพบว่านี่เป็นทางออกที่ดีสำหรับส่วนใหญ่:

SELECT * FROM table ORDER BY ISNULL(field), field ASC;

6
โดยไม่ต้องกําหนดการสั่งซื้อจากผลงาน: SELECT * FROM table ORDER BY ISNULL(field) ASC;(MySQL 5.5)
MARCAL ฆ

5
นี่เป็นทางออกที่ดีกว่า
Rok Kralj

4
โซลูชันที่ยอมรับไม่ทำงานกับ TIMESTAMP ใน postgresql 9.3 วิธีนี้ใช้ ...
kalu

2
น่ารำคาญ MySQL จะไม่ใช้ดัชนีในฟิลด์เมื่อคุณเพิ่ม isnull (ฟิลด์) ในการสั่งซื้อตามข้อ (เมื่อใช้วงเงิน)
Barry Kelly

3
@kalu: ในPostgreSQLค่า NULL จะเรียงลำดับสุดท้ายตามลำดับจากน้อยไปหามาก (และเรียงจากมากไปหาน้อย) และคุณค่อนข้างจะใช้มาตรฐาน SQLข้อNULLS LAST| NULLS FIRSTเพื่อพลิกแทนวิธีแก้ปัญหาที่นี่
Erwin Brandstetter

23

สิ่งที่ต้องการ

SELECT * FROM tablename where visible=1 ORDER BY COALESCE(position, 999999999) ASC, id DESC

แทนที่ 999999999 ด้วยค่าสูงสุดสำหรับฟิลด์


3
การแก้ปัญหานี้มีความเปราะบางและอาจนำไปสู่ข้อผิดพลาดเป็นระยะ ๆ
Dmitry Bogdanovich


4

คุณสามารถสลับอินสแตนซ์ของ NULL ด้วยค่าที่แตกต่างเพื่อเรียงลำดับก่อน (เช่น 0 หรือ -1) หรือสุดท้าย (เป็นจำนวนมากหรือตัวอักษร) ...

SELECT field1, IF(field2 IS NULL, 9999, field2) as ordered_field2
  FROM tablename
 WHERE visible = 1
 ORDER BY ordered_field2 ASC, id DESC

สิ่งนี้จะไม่แก้ปัญหาเนื่องจากดัชนีที่อ้างอิงใน ORDER BY จะไม่ได้รับผลกระทบจากการแทนที่ค่าในคำสั่ง SELECT และด้วยเหตุนี้จะไม่แก้ไขการสั่งซื้อ นอกจากนี้ให้ตรวจสอบฟังก์ชัน COALESCE ซึ่งเทียบเท่ากับการใช้ฟังก์ชัน IF ของคุณ
กำหนด

หากคุณใช้นามแฝงคำสั่ง IF อย่างถูกต้องแถวต่างๆจะเรียงตามที่คุณต้องการ ฉันแก้ไขตัวอย่างของฉัน
Langdon

4

ลองใช้แบบสอบถามนี้:

SELECT * FROM tablename
WHERE visible=1 
ORDER BY 
CASE WHEN position IS NULL THEN 1 ELSE 0 END ASC,id DESC

ไม่จำเป็นต้องใช้เคส IS NULL ส่งคืน 1 เมื่อนิพจน์เป็น NULL ดูคำตอบของเสียงก้อง
contactmatt

3

คุณสามารถรวม NULL ของคุณในORDER BYคำสั่ง:

select * from tablename
where <conditions>
order by
    coalesce(position, 0) ASC, 
    id DESC

หากคุณต้องการ NULLs coalesce(position, 100000)การจัดเรียงอยู่ด้านล่างลอง (ทำให้ตัวเลขตัวที่สองใหญ่กว่าค่าอื่น ๆpositionใน db.)


3
SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC

6
ทำไม OP ควรลองนี้ ? คำตอบที่ดีมักจะมีคำอธิบายเกี่ยวกับสิ่งที่ทำและเหตุผลที่ทำเช่นนั้นไม่เพียง แต่สำหรับ OP แต่สำหรับผู้เยี่ยมชมในอนาคตที่อาจพบคำถามนี้และอ่านคำตอบของคุณ
RiggsFolly

2

สำหรับDATEคอลัมน์คุณสามารถใช้:


NULLS ครั้งสุดท้าย:

ORDER BY IFNULL(`myDate`, '9999-12-31') ASC

ช่องว่างสุดท้าย:

ORDER BY IF(`myDate` = '', '9999-12-31', `myDate`) ASC

1

เพื่อให้บรรลุผลลัพธ์ต่อไปนี้:

1, 2, 3, 4, NULL, NULL, NULL.

ไวยากรณ์ USE, ทำ-(minus sign)ก่อนชื่อฟิลด์และใช้ inv_start_type (เช่น: หากคุณต้องการสั่งซื้อโดยคำสั่ง ASC แล้วใช้ DESC หรือถ้าคุณต้องการคำสั่ง DESC แล้วใช้ ASC)

SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC



-8

ทำไมคุณไม่สั่งโดย NULLS LAST

SELECT * 
FROM tablename
WHERE visible = 1 
ORDER BY position ASC NULLS LAST, id DESC 

NULLS LAST- มีการแนะนำ MySQL รุ่นใด?
crmpicco

2
@Panique คุณหมายถึง (MS) SQL Server หรือไม่
d -_- b

1
คำตอบนี้ใช้ไม่ได้กับ MySQL
PeppyHeppy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.