วิธีการกำหนด ORDER BY แบบกำหนดเองใน mySQL


143

ใน MySQL ฉันจะกำหนดลำดับการเรียงแบบกำหนดเองได้อย่างไร

เพื่อพยายามอธิบายสิ่งที่ฉันต้องการพิจารณาตารางนี้:

ID  Language    Text
0   ENU         a
0   JPN         b
0   DAN         c       
1   ENU         d
1   JPN         e
1   DAN         f
2   etc...

ที่นี่ฉันต้องการกลับแถวทั้งหมดเรียงตามภาษาและจากน้อยไปมาก ID เพื่อให้ Language = ENU มาก่อนจากนั้น JPN และสุดท้าย DAN

ผลลัพธ์ควรเป็น: a, d, b, e, c, f เป็นต้น

เป็นไปได้ไหม

คำตอบ:


276

MySQL มีฟังก์ชั่นที่เรียกว่าสะดวกFIELD()ซึ่งยอดเยี่ยมสำหรับงานเช่นนี้

ORDER BY FIELD(Language,'ENU','JPN','DAN'), ID

อย่างไรก็ตามโปรดทราบว่า

  1. ทำให้ SQL แบบพกพาของคุณน้อยลงเนื่องจาก DBMS อื่นอาจไม่มีฟังก์ชันดังกล่าว

  2. เมื่อรายการภาษาของคุณ (หรือค่าอื่น ๆ ที่จะเรียงลำดับ) ยาวขึ้นจะเป็นการดีกว่าถ้าคุณมีตารางแยกต่างหากพร้อมคอลัมน์เรียงลำดับสำหรับพวกเขาและเข้าร่วมกับแบบสอบถามของคุณเพื่อสั่งซื้อ


3
ขอบคุณนี้เหมาะสำหรับสถานการณ์ของฉันที่ฉันต้องสั่งสองค่า (ภาษาหลักเช่น JPN และภาษาทางเลือกเช่น ENU)
Muleskinner

4
ผู้ชายคุณเพียงแค่บันทึกฉันเขียนในวีโอไอพี :)
เอริค Simonic

1
ถ้าคุณมีGROUP BYมาก่อน ตัวอย่างเช่นค่าแรกที่ฉันต้องการปรากฏที่ท้าย?
Pathros

ใส่แบบสอบถามด้วยGROUP BYในแบบสอบถามย่อยและสั่งซื้อในแบบสอบถามด้านนอก
Mchl

1
ทำงานเหมือนมีมนต์เสน่ห์ :)
Brane

53

หากผู้ที่มีเพียงสามค่าแล้วคุณสามารถใช้แสดงออก :CASE

ORDER BY `ID`,
         CASE `Language`
         WHEN 'ENU' THEN 1
         WHEN 'JPN' THEN 2
         WHEN 'DAN' THEN 3
         END

(หากอาจมีค่าอื่น ๆ คุณอาจต้องการเพิ่มตรรกะพิเศษบางอย่างเพื่อให้การสั่งซื้อสอดคล้องกันตัวอย่างเช่นคุณอาจเพิ่มELSE 4ในCASEนิพจน์นั้นแล้วเรียงลำดับด้วยLanguageตัวเองเป็นเกณฑ์การเรียงลำดับที่สาม:

ORDER BY `ID`,
         CASE `Language`
         WHEN 'ENU' THEN 1
         WHEN 'JPN' THEN 2
         WHEN 'DAN' THEN 3
         ELSE 4
         END,
         `Language`

)


1
และหากมีค่าภาษาจำนวนมากคุณสามารถมีตารางแยกเก็บแต่ละภาษาพร้อมคอลัมน์เรียงลำดับและเชื่อมโยงไปยังที่
kaj

1
จะเรียงลำดับตาม ID ก่อนส่งผลให้ a, b, c, d, e, f
piotrm

ขอบคุณสิ่งนี้ใช้ได้อย่างสมบูรณ์แบบ - เช่นเดียวกับ Mchl ที่ฉันตอบรับซึ่งดูง่ายกว่านี้
Muleskinner

19

คุณมีทางเลือกสองทางอย่างแรกคือการเปลี่ยนภาษาเป็น ENUM (สมมติว่าเป็นไปได้และคุณคาดหวังเพียงไม่กี่รูปแบบ)

หากคุณระบุว่าเป็นENUM('ENU','JPN','DAN')แล้วORDER Language ASCจะสั่งในลำดับที่คุณระบุ

กรณีที่สองจะเกี่ยวข้องกับกรณีเช่น

SELECT * FROM table
ORDER BY CASE Language
    WHEN 'ENU' THEN 3
    WHEN 'JPN' THEN 2
    WHEN 'DAN' THEN 1
    ELSE 0
END DESC, ID ASC

ประสิทธิภาพที่ดีขึ้นวิธีการ ENUM จะให้ผลลัพธ์ที่เร็วขึ้น แต่จะยุ่งยากกว่าหากคุณต้องการเพิ่มภาษาอื่น ๆ ตัวเลือกที่สามคือการเพิ่มตารางการทำให้เป็นมาตรฐานสำหรับภาษาอย่างไรก็ตามที่อาจ overkill ในอินสแตนซ์นี้


คุณพิมพ์อยู่ENUM('ENU','JPN','DAN')ที่ไหน
Pathros

1
@pathros ในคำจำกัดความของตารางคุณระบุว่าเป็น ENUM แทน VARCHAR เป็นต้น MySQL จะจัดเก็บตัวเลือก ENUM ไว้ในลำดับที่เฉพาะเจาะจงและจัดทำดัชนีและเมื่อสั่งซื้อโดยคอลัมน์ ENUM โดยเฉพาะมันจะใช้ดัชนีภายในนั้นแทน ค่าสตริง (ยกเว้นว่านักแสดง () ใช้เพื่อทำให้มันกลับไปเป็น VARCHAR)
Simon ที่พอร์ทัลโรงเรียนของฉัน

ไม่ควรEND DESC,จะเป็นEND CASE DESC,?
Istiaque Ahmed

Nope ไม่CASEจำเป็นทั้งหมดEND CASEมันขึ้นอยู่กับบริบท CASEภายใน PROCEDURE ต้องการEND CASE( dev.mysql.com/doc/refman/5.5/en/case.html ) อย่างไรก็ตามCASEภายใน SELECT ไม่จำเป็นต้องใช้END CASEเพียงแค่END( dev.mysql.com/doc/refman/5.7/en/ … ) - ในส่วนนี้ บริบทมันเป็นฟังก์ชั่นการไหลของการควบคุม
Simon ที่พอร์ทัลโรงเรียนของฉัน

1

สำหรับเฟรมเวิร์ก Yii2 เรายึดตำแหน่งให้สำเร็จด้วยวิธีต่อไปนี้

Project::find()
->orderBy([new Expression('FIELD(pid_is_t_m,2,0,1)'),'task_last_work'=> SORT_ASC])
->all();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.