ใน MySQL กรณีเราต้องการหาค่าสูงสุด ตำสุด ในชุดข้อมูลนั้น ๆ จะหาได้จากการใช้ฟังก์ชั่น MIN() ซึ่งจะคืนค่าตำสุดและ MAX() จะคืนค่าสูงสุดในฟิลด์ที่ระบุ เช่น
SELECT MIN(column_name) FROM TABLE_NAME
กรณีที่หาค่าต่ำสุด/สูงสุด แยกตาม กลุ่มใด ๆ ก็ตามเพียงแค่ใช้ GROUP BY ต่อแค่นั้น
จบแล้วเหรอ เด๋วก่อนนนนนน !!! ชีวิตมันไม่ง่ายขนาดนั้น มันจะมีความต้องการอีกกรณีนึงคือ
อยากได้ค่า X ในเรคคอร์ดที่มีค่าสูงสุดในฟิลด์ที่ระบุ (Y) แต่ไม่ใช่ค่า Y นะ แยกตามกลุ่ม Z
ดูตัวอย่างข้อมูลดีกว่า
ค่า X คือ LABRESULT
ค่า Y คือ DATE_SERV
ค่า Z คือ CID
เพราะฉะนั้นผลลัพธ์ที่ได้ควรจะเป็นเช่นนี้ ที่เธอต้องการ
เราสามารถเขียนคำสั่งได้หลายแบบ อาทิ
แบบที่ 1
SELECT * FROM ( SELECT HOSPCODE,CID,DATE_SERV,LABTEST,LABRESULT FROM demolasteachgroup ORDER BY DATE_SERV DESC ) t1 GROUP BY CID;
แบบที่ 2
SELECT * FROM demolasteachgroup WHERE DATE_SERV IN ( SELECT MAX(DATE_SERV) FROM demolasteachgroup GROUP BY CID );
แบบที่ 3
SELECT t1.* FROM demolasteachgroup t1 LEFT JOIN demolasteachgroup t2 ON (t1.CID = t2.CID AND t1.DATE_SERV < t2.DATE_SERV) WHERE t2.CID IS NULL;
ปล 1. จากการทดสอบพบว่า
MySQL Version | แบบที่ 1 | แบบที่ 2 | แบบที่ 3 |
5.5 | √ | √ | √ |
5.6 | √ | √ | √ |
5.7 | × | √ | √ |
10.2.2 (MariaDB) | × | √ | √ |
√ ผลลัพธ์ถูกต้อง
× ผลลัพธ์ผิด
ปล. 2 ตัดเงื่อนไขเรื่อง Big O นะ มองถึงผลลัพธ์ที่ถูกต้องอย่างเดียว
ปล. 3 มีประเด็นสงสัยจากเพื่อนในวงการ(สุขภาพ) ถามมาที่จับใจความได้ก็ (ถ้ามีเพิ่มเติมก็ discuss กันได้นะครับ ยินดี)
Q : ยกตัวอย่างที่เป็นรูปธรรมเห็นได้หน่อยที่บอกว่าความต้องการอีกกรณีนึง
A : เช่น ต้องการหาค่าน้ำตาลล่าสุดxxของผู้ป่วยหรือผลแลป HbA1C ล่าสุดของผู้ป่วย เป็นต้น กรณีหากได้ค่าที่ผิดพลาดออกมามีผลอย่างมาก เพราะ 2 รายการข้างต้นเป็นหนึ่งในเงื่อนไขที่บอกถึงการควบคุมน้ำตาลได้ดีของผู้ป่วย ซึ่งอยู่ใน KPI ทุก ๆ ปีของคนทำงานด้านสุขภาพ (คนไทยเป็นเบาหวานเยอะมากนะ อันนี้เป็นเรื่องน่ากังวลเหมือนกัน) KPI เกือบผ่านหรือเกือบไม่ผ่านความรุนแรงในการตำหนิต่างกันเยอะ ^_^
Q : ทดสอบกับ MySQL คนละ Version ให้ผลไม่เหมือนกัน อะไร ยังไง
A : ที่ให้ผลลัพธ์ไม่ถูกต้องนั้น เฉพาะแบบที่ 1 นะ ตามปล. 1 คือตัวนี้
SELECT * FROM ( SELECT HOSPCODE,CID,DATE_SERV,LABTEST,LABRESULT FROM demolasteachgroup ORDER BY DATE_SERV DESC ) t1 GROUP BY CID;
ดูรูปหล่ะกัน เราจัดเรียงข้อมูลตามวันที่เพื่อหาล่าสุด กวาด ๆ ด้วยตาจะเห็นว่ากรอบสีแดงคือเรคคอร์ดที่ถูกต้อง ที่คำสั่ง SQL ควรจะคืนผลลัพธ์มา
แต่ผลลัพธ์จะผิดทันทีถ้าใช้ MySQL Version 5.7 เป็นต้นไป (ปัจจุบันเวอร์ชั่น 5.7.17)
** ไม่ได้หาสาเหตุนะว่าผิดเพราะอะไร ใครจะลองไปทดสอบเวอร์ชั่นอื่น ๆ คำสั่งที่ใช้ทดสอบก็ตามนี้
MySQL 5.5 – http://sqlfiddle.com/#!2/38ef1b/2
MySQL 5.6 – http://sqlfiddle.com/#!9/38ef1b/4
MySQL 5.7 – http://rextester.com/JALDD35756