เคสแรกหล่ะกัน กรณีกำหนด Key เป็น Auto increment ใน MySQL แล้วเลขลำดับ/Key/IDs บางตัวหายไป (หลายสาเหตุ) ลองมาทำ Dummy Table ทดสอบดูกัน CREATE TABLE numbers( startNumber INTEGER UNSIGNED, PRIMARY KEY (`startNumber`) ); ALTER TABLE numbers ADD INDEX idx1 (startNumber); INSERT INTO numbers VALUES (1),(2),(3),(4),(5),(6),(8),(9),(20),(21),(22),(53),(54), (71),(72),(74),(80); จากตารางดัมมี่ข้างต้นผลลัพธ์ที่เราต้องการคือตัวเลข 7, 10-19, 23-52, 55-70, 73, 75-79 ลองเขียนคำสั่งเพื่อให้ได้คำตอบด้านบนหลายวิธี วิธีแรกต้องใช้ตาราง Sequence Number ใน MySQL อาจต้องทำ Manual ไปก่อน วิธีแรก …
Tag Archives: MySQL
หาจำนวนรายใหม่โดยใช้การเปรียบเทียบระหว่างแถวใน MySQL
วันนี้บล็อกสั้น ๆ จากหัวข้อไม่งงกันใช่ไหม ^__^ อธิบายคร่าว ๆ คือกรณีเรามีตารางที่เก็บจำนวนสะสมไว้ในแต่ละวัน เวลาเราต้องการทราบว่าแล้ววันนี้มีเพิ่มเข้ามาใหม่เท่าไหร่ โดยทั่วไปทำมือก็อาจจะ นับจำนวนเฉพาะรายที่มาใหม่ไง หรือเอาจำนวนสะสมของวันนี้/ตอนนี้ ไปลบกับวันที่แล้ว ใช่นั่นแหล่ะทำด้วยมือ แล้วในภาษา SQL เค้าทำยังไงกัน ให้เห็นภาพมากขึ้นเราจะเอาข้อมูลรายงานเคสโควิด 19 ของประเทศไทยในแต่ละวันมาเป็นข้อมูลดัมมี่หล่ะกัน (ข้อมูลจริงนะ นี่ ศบค. รายงานทุกวัน อยากได้ข้อมูลก็ไปที่กรมควบคุมโรค ที่นี่เลย https://covid19.ddc.moph.go.th/th/api) *เราตัดเฉพาะยอดสะสมของแต่ละวันในเดือนพฤษภาคมหล่ะกัน เพื่อจะได้ง่ายขึ้น CREATE TABLE `covid19timeline` ( `ConfirmedDate` date NOT NULL, `Confirmed` int(11) NOT NULL, `Recovered` int(11) NOT NULL, `Hospitalized` int(11) NOT NULL, `Deaths` int(11) NOT NULL, PRIMARY KEY (`ConfirmedDate`) …
Continue reading “หาจำนวนรายใหม่โดยใช้การเปรียบเทียบระหว่างแถวใน MySQL”
ลบแถวที่ซ้ำกันใน MySQL
เมื่อมีข้อมูลซ้ำเกิดขึ้นในตารางจะด้วยสาเหตุอะไรก็แล้วแต่ แต่มันมีข้อมูลซ้ำเกิดขึ้นแล้วและเราต้องการลบตัวที่ซ้ำออกไป เราจะทำยังไงมาดูแนวทางกัน เริ่มต้นเราดูตัวอย่างข้อมูลที่ซ้ำกันก่อน DROP TABLE IF EXISTS contacts; CREATE TABLE contacts ( id INT PRIMARY KEY AUTO_INCREMENT, first_name VARCHAR(50) NOT NULL, last_name VARCHAR(50) NOT NULL, email VARCHAR(255) NOT NULL ); INSERT INTO contacts (first_name,last_name,email) VALUES (‘Carine ‘,’Schmitt’,’[email protected]’), (‘Jean’,’King’,’[email protected]’), (‘Peter’,’Ferguson’,’[email protected]’), (‘Janine ‘,’Labrune’,’[email protected]’), (‘Jonas ‘,’Bergulfsen’,’[email protected]’), (‘Janine ‘,’Labrune’,’[email protected]’), (‘Susan’,’Nelson’,’[email protected]’), (‘Zbyszek ‘,’Piestrzeniewicz’,’[email protected]’), (‘Roland’,’Keitel’,’[email protected]’), (‘Julie’,’Murphy’,’[email protected]’), (‘Kwai’,’Lee’,’[email protected]’), (‘Jean’,’King’,’[email protected]’), (‘Susan’,’Nelson’,’[email protected]’), (‘Roland’,’Keitel’,’[email protected]’); …
ใช้ MySQL หาค่าค่าสุดท้ายเมื่อตอนอดีตแต่ตอนนี้คือปัจจุบัน(ซึ่งมันเปลี่ยนไปเยอะแล้ว)
อย่าเพิ่งงงกับชื่อเรื่อง คือมันมีที่มา คือเมื่อสองสามวันก่อนมีคนไปตั้งโพสต์ถามในกลุ่มประมาณ 2-3 กลุ่ม (นี่ก็ตามอยู่)ซึ่งเป็นกลุ่มที่เกี่ยวข้องกับคอมพิวเตอร์เป็นกลุ่มใหญ่เลยทีเดียว คำถามคือ ดูรูปเอานะ จากที่ดูโจทย์ ตาราง drug_catalog เก็บรายการยาและการเปลี่ยนแปลงราคา ตาราง drug_order เก็บรายการสั่งยาของผู้ป่วยแต่ละคน ผลลัพธ์ที่ต้องการคือต้องการราคายา ณ วันที่สั่ง ซึ่งวันที่สั่งคือราคาล่าสุดแต่เดี๋ยวก่อนซึ่งมันดันเป็นอดีตไปแล้วสำหรับราคายาและการสั่งยาแต่ละรายการ ปัจจุบันรายการยามีการปรับปรุงราคามาหลายรอบแล้ว จากในเมนท์ได้รู้ว่า ไม่สามารถเปลี่ยนโครงสร้างให้ดีกว่าได้ ^_^ , มีการบันทึกราคาในตารางสั่งยาผิดนี่คือต้องการแก้ไขเอาราคาที่ถูก ณ เวลาที่สั่งยาเข้าไป ซึ่งก็นั่นแหล่ะเลยพอจะเดาได้ว่านี่แค่ดัมมี่ข้อมูลเพื่อเอามาถามหา Solution แก้ไขเฉย ๆ (ในความเป็นจริงแล้วคนที่อยู่ในฟิลด์โปรแกรมด้านการพยาบาลมันละเอียดกว่านี้เยอะ) แต่ช่างเหอะ มาดูการหาคำตอบกัน ซึ่งแต่ละวิธีมีทั้งผิดและถูก คือถ้าถูกก็ยังอาจไม่จบคือผลลัพธ์ถูกแต่มันมีปัจจัยเรื่อง Performance อะไรอีกเยอะแยะ ข้อมูลจริงอาจมีเป็นหลายล้านเรคคอร์ดซึ่งก็ต้องไปหาสิ่งที่เหมาะสมต่อไป ทำไมถึงเอาโจทย์นี้มาทำ ? ไอ้รายการยา การสั่งยา ผู้ป่วย ไรเทือกนี้คุ้นชินอยู่และไม่ช้าอาจจะเจอเคสแบบนี้ รวมทั้งการแก้โจทย์มันเป็นหนึ่งในการพัฒนาสกิลด้วย ทำบ่อย ๆ ค่อย ๆ ชิน #ความรักก็เช่นกัน เริ่มหาคำตอบกันโดยผลลัพธ์แบบชัด ๆ คือขยายเฉย …
MySQL ว่าด้วยลำดับและการจัดอันดับข้อมูล
เดิมทีแล้ว MySQL ไม่มีฟังก์ชั่น (Row Number) สำหรับเรียกลำดับที่ (1, 2, 3 …n) ของแถว/เร็คคอร์ดในฐานข้อมูลเหมือนดั่งเช่นเจ้าอื่น ๆ เพราะฉนั้นเหล่านักรบส่วนใหญ่ก็มักสร้างฟังก์ชั่นใส่ลำดับที่แถวเอง สมมุติเรามีชุดข้อมูลนึงแสดงคะแนนของแต่ละอำเภอ (เอ๊ะ !! คุ้น ๆ ) ตามนี้ CREATE TABLE IF NOT EXISTS `rstanding` ( `id` int(6) unsigned NOT NULL, `name` varchar(20) NOT NULL, `score` decimal(10,2) NOT NULL, PRIMARY KEY (`id`) ) DEFAULT CHARSET=utf8; INSERT INTO `rstanding` (`id`, `name`, `score`) VALUES (‘1’, ‘A’, …
MySQL แสดงผลวันที่แบบไทย (แบบเต็มและแบบย่อ)
การแสดงผลวัน เดือน ปี ของ MySQL จะแสดงผลเป็นวันที่ในรูปแบบสากลคือในรูปแบบภาษาอังกฤษจะแบบเต็มหรือแบบย่อก็ยังเป็นภาษาอังกฤษอยู่ดี ซึ่งในภาษาอื่นก็ยังไม่รองรับการแสดงผลในภาษาท้องถิ่นนั้น ๆ (รวมทั้งฟังก์ชั่นที่สามารถใช้งานด้วย) ในกรณีที่ต้องการแสดงผล วัน เดือน ปี เป็นภาษาไทยจึงจำเป็นต้องสร้างฟังก์ชั่นขึ้นมาใช้งานเองซึ่งเราจะมาเขียนฟังก์ชั่นนี้กันโดยอาศัยฟังก์ชั่นของ MySQL ที่ชื่อว่า SUBSTRING_INDEX() Return a substring of a string before a specified number of delimiter occurs Syntax SUBSTRING_INDEX(string, delimiter, number) Parameter Values string Required. The original string delimiter Required. The delimiter to search for number Required. The number of times to …
Continue reading “MySQL แสดงผลวันที่แบบไทย (แบบเต็มและแบบย่อ)”
MySQL Get First value or Last value in each group
ใน MySQL ตั้งแต่เวอร์ชั่น 8.0 เป็นต้นไป ถ้าต้องการดึงค่าแรกและค่าสุดท้ายในกรุ๊ปนั้น ๆ ออกมา สามารถใช้ Function FIRST_VALUE() FIRST_VALUE(expr) [null_treatment] over_clause Returns the value of expr from the first row of the window frame. LAST_VALUE() LAST_VALUE(expr) [null_treatment] over_clause Returns the value of expr from the last row of the window frame. ตัวอย่างการใช้งาน โจทย์ มีข้อมูล CKD Stage (สมมุติ) เรียงตามรายปีงบประมาณ ถ้าต้องการทราบ Stage แรกและสุดท้ายที่ตรวจพบในรายนั้น ๆ …
Continue reading “MySQL Get First value or Last value in each group”
MySQL generates a sequence of numeric values
หลังจากได้อ่านและลอง Sequence ใน MariaDB 10.3 แล้ว มันช่างง่ายเหลือเกินให้ตายเถอะโรบิน (แนะนำให้ไปอ่านยังไงก็ได้ใช้แน่ ๆ ) แต่บล๊อกนี้เราจะไม่ได้เขียนเรื่องนี้ 5555 เราจะใช้วิธีที่เรียกว่า CTE (Common Table Expression) สำหรับการสร้างชุดข้อมูล CTE ซึ่งเริ่มใช้ได้ใน MySQL 8.0, MariaDB 10.2 เป็นต้นมาซึ่งเอาจริง ๆ ก็ง่ายพอ ๆ กันแหล่ะ เราเคยเขียนในบทความเก่า ๆ ลองไปหาอ่านกันได้ หรือของ อ.ประเสริฐ ลักษณของ CTE ใช้การเรียกโดยวิธี Recursive รูปแบบใน MySQL จะเป็นแบบนี้ with_clause: WITH [RECURSIVE] cte_name [(col_name [, col_name] …)] AS (subquery) [, cte_name [(col_name [, …
Continue reading “MySQL generates a sequence of numeric values”
Split comma separated string to multiple rows
สำหรับใครที่เคยใช้ฟังก์ชั่น GROUP_CONCAT() ใน MySQL มาก่อนก็พอจะเดาผลลัพธ์จากฟังก์ชั่นนี้ได้ว่า ผลลัพธ์จะเป็นค่าตามคอลัมภ์ที่ถูกกรุ๊ป (GROUP BY) และนำมาต่อกันด้วยเครื่องหมายที่ระบุ ปกติค่าดีฟอลต์จะเป็น comma ‘,’ รูปแบบคำสั่งก็จะประมาณนี้ GROUP_CONCAT([DISTINCT] expr [,expr …] [ORDER BY {unsigned_integer | col_name | expr} [ASC | DESC] [,col_name …]] [SEPARATOR str_val]) ตัวอย่าง **ภาพจาก mysqltutorial ข้างบนนี่คือต้นเหตุ มักจะมีกรณีที่เราได้ผลลัพธ์มาแล้ว นั่นคือ “A,B,C” และเราต้องการแยกข้อความที่ได้มาออกเป็นแต่ละแถว (ตาราง t ก่อนที่จะผ่านฟังก์ชั่น GROUP_CONCAT() นั่นแหล่ะ) ดูตัวอย่างกัน CREATE TABLE DEMO ( ID INTEGER PRIMARY KEY AUTO_INCREMENT, PID …
Continue reading “Split comma separated string to multiple rows”
Hierarchical and recursive queries in MySQL
Hierarchical query คืออะไร ? A hierarchical query is a type of SQL query that handles hierarchical model data. They are special cases of more general recursive fixpoint queries, which compute transitive closures. อยากบอก(บ่น) ว่าก่อนที่ MySQL 8 จะออกนี่การดึงข้อมูลแบบลำดับชั้นลักษณะต้นไม้ (Tree) แบบนี้โคตรเปลืองพลังงาน แต่ตอนนี้ดีขึ้นมาก ต้องขอบคุณจริง ๆ ที่ MySQL อิมพลีเมนต์ Common Table Expression (CTE) ให้ใช้ได้ซะที เขียนคำสั่งสั้นลง ประสิทธิภาพดีขึ้น (ก็แหงสิเจ้าของเค้าทำออกมาเอง) ยกตัวอย่างข้อมูลลักษณะแบบลำดับชั้น เช่น …
Continue reading “Hierarchical and recursive queries in MySQL”