หลายครั้งที่เราได้โจทย์ หรือปัญหามาแก้โดยใช้วิธีการ Query จากฐานข้อมูลมา ซึ่งมีรูปแบบการ Query หลายแบบ ได้แก่ การเขียน JOIN ตาราง, UNION หรือ ทำเป็น Sub Query เป็นต้น ในวันนี้ผมขอนำเสนอวิธีการเขียน SELECT IN SELECT ซึ่งเป็นวิธีการเขียน Query แบบหนึ่งที่ช่วยแก้ปัญหาได้มากมาย และลดการเขียน Coding ที่ไม่จำเป็นได้อีก
ตัวอย่างปัญหา เราต้องการดูข้อมูลการจ่ายดอกเบี้ยทั้งหมด เพื่อนำมาออกรายงาน โดยมีเงื่อนไขดังนี้
- ข้อมูลการจ่ายดอกเบี้ยในเดือนเดือนกัน ให้นำมารวมกัน
- ข้อมูลการจ่ายดอกเบี้ยช่วงระหว่างเดือน ให้แยกกลุ่มออกมา เช่น จ่ายดอกเบี้ยระหว่างวันที่ 2014-04-21 ถึง 2014-05-06 ระบบต้องตีความเป็นการจ่ายดอกเบี้ยระหว่างเดือน เมษายน ถึง เดือนพฤษภาคม
ข้อมูลที่ใช้กับตัวอย่างนี้
============================================================================================ TX ID | TX TYPE | TX CLASS | TX SUBCLASS | CUSTOMER | COSTAMOUNT | DATE FROM | DATE TO ============================================================================================ 1001 | WITHDRAW | CASH | INTEREST | CUS01 | 50,000.00 | 2014-04-01 | 2014-04-12 1002 | DEPOSIT | CASH | RENT | CUS01 | 20,000.00 | 2014-04-01 | 2014-04-04 1003 | WITHDRAW | CASH | INTEREST | CUS02 | 34,200.00 | 2014-04-01 | 2014-04-08 1004 | WITHDRAW | CASH | INTEREST | CUS01 | 12,000.00 | 2014-04-15 | 2014-04-23 1005 | WITHDRAW | CASH | INTEREST | CUS02 | 50,000.00 | 2014-04-09 | 2014-04-18 1006 | WITHDRAW | CASH | INTEREST | CUS01 | 20,000.00 | 2014-04-15 | 2014-05-16 1007 | WITHDRAW | CASH | INTEREST | CUS02 | 12,300.00 | 2014-04-21 | 2014-05-16
ขั้นตอนการแก้ปัญหา (ถ้ามีการเขียน SQL ผมขอใช้ SYNTAX ของ SQL Server นะครับ)
- Query ข้อมูลการตัดจ่ายดอกเบี้ย โดยต้องกำหนดเงื่อนไขของ DATE FROM กับ DATE TO ว่าอยู่ในเดือนเดียวกัน หรือระหว่างเดือน ซึ่งจากข้อมูลที่ให้มาผลลัพธ์ที่ได้ ควรออกมา ดังนี้
=============================================================================== TX ID | TX TYPE | TX CLASS | TX SUBCLASS | CUSTOMER | COSTAMOUNT |MONTH RANGE =============================================================================== 1001 | WITHDRAW | CASH | INTEREST | CUS01 | 50,000.00 | APR 1003 | WITHDRAW | CASH | INTEREST | CUS02 | 34,200.00 | APR 1004 | WITHDRAW | CASH | INTEREST | CUS01 | 12,000.00 | APR 1005 | WITHDRAW | CASH | INTEREST | CUS02 | 50,000.00 | APR 1006 | WITHDRAW | CASH | INTEREST | CUS01 | 20,000.00 | APR - MAY 1007 | WITHDRAW | CASH | INTEREST | CUS02 | 12,300.00 | APR - MAY
โดยใช้ Query ที่มีการตรวจสอบเงื่อนไขของ DATE FROM กับ DATE TO ว่าเป็นเดือนเดียวกัน หรือต่างเดือนกัน ดังนี้
SELECT txid, txtype, txclass, txsubclass, costamount, CASE WHEN Month(datefrom) = Month(dateto) AND Year(datefrom) = Year(dateto) THEN CONVERT(VARCHAR(3), Datename(month, datefrom)) ELSE CONVERT(VARCHAR(3), Datename(month, datefrom)) + ' - ' + CONVERT(VARCHAR(3), Datename(month, dateto)) END AS MONTHRANGE FROM txtest CTX WHERE CTX.txtype = 'WITHDRAW' AND CTX.txclass = 'CASH' AND CTX.txsubclass = 'INTEREST'
- Query ข้อมูลที่ได้จากข้อที่แล้วมา Query ซ้อนอีกครั้ง เพื่อหาผลรวมในแต่และเดือน และระหว่างเดือนมีการจ่ายดอกเบี้ยออกไปเท่าไหร่ ซึ่งจากข้อมูลในข้อที่แล้วผลลัพธ์ที่ได้ควรออกมา ดังนี้
============================================================== TX TYPE | TX CLASS | TX SUBCLASS | COSTAMOUNT | MONTH RANGE ============================================================== WITHDRAW | CASH | INTEREST | 146,200.00 | APR WITHDRAW | CASH | INTEREST | 32,300.00 | APR - MAY
โดยจะ SELECT ซ้อนครอบอีกขั้นนึง เพื่อที่เอาผลลัพธ์ที่ได้จาก Query ก้อนด้านในมา SUM หาผลรวมอีกที ดังนี้
SELECT TMP.txtype, TMP.txclass, TMP.txsubclass, Sum(TMP.costamount), TMP.monthrange FROM (SELECT txid, txtype, txclass, txsubclass, costamount, CASE WHEN Month(datefrom) = Month(dateto) AND Year(datefrom) = Year(dateto) THEN CONVERT(VARCHAR(3), Datename(month, datefrom)) ELSE CONVERT(VARCHAR(3), Datename(month, datefrom)) + ' - ' + CONVERT(VARCHAR(3), Datename(month, dateto)) END AS MONTHRANGE FROM txtest CTX WHERE CTX.txtype = 'WITHDRAW' AND CTX.txclass = 'CASH' AND CTX.txsubclass = 'INTEREST') TMP GROUP BY TMP.txtype, TMP.txclass, TMP.txsubclass, TMP.monthrange
หมายเหตุ: โจทย์นี้อาจจะมีวิธีการอื่นๆในการเขียน Query เพื่อให้ได้ผลลัพธ์ที่เหมือนกัน แต่ที่ผมยกตัวอย่างนี้มา เพื่อที่จะสร้าง Idea และแนวทางให้การปรับประยุกต์ใช้ต่อไปนะครับ
Discover more from naiwaen@DebuggingSoft
Subscribe to get the latest posts sent to your email.