Mine

รูปภาพของฉัน
หาดใหญ่, ภาคใต้, Thailand
ชอบเอาใจ แต่ก็เอาแต่ใจ

วันจันทร์ที่ 11 กรกฎาคม พ.ศ. 2554

เมื่อจำเป็นต้องใช้ พ.ร.บ. รถจักรยานยนต์

เหตุเกิดเมื่อวันที่ 9 เมษายน 2554 เวลาประมาณบ่าย 2 โมง หลานมาบอกว่า น้องภัทร อยู่อนามัย เท้าเข้าล้อรถ อึ้งไปพักนึง เลยปลุกชอว์บอกว่าลูกอยู่อนามัย ก็ขับรถออกมาที่อนามัย ก็ยังไม่เห็นแผลเพราะเขาปิดแผลหมดแล้ว รู้แต่ว่าเขาบอกให้ไปโรงพยาบาล ก็ขับรถไปโรงพยาบาล ... จนกระทั่ง พยาบาลมาเปิดแผล แม่เจ้า ไม่ใช่น้อย ๆ (ไม่อยากอธิบายเรื่องแผล เจ็บใจ ขอบอกคำเดียวว่า เซ็ง)

เราเป็นคนไม่มีความรู้ทางด้านสาธารณสุข ก็คงได้แต่ทำตามที่เขาบอกเขาให้ทำ ถึงจะขัดใจบ้าง ก็ยังปลอบใจตัวเองว่า "เราเชื่อหมอก็หายไปครึ่งแล้ว อีกครึ่งอยู่ที่ฝีมือหมอ" เป็นตอนนี้อยากถอนคำพูด ล้างแผลอยู่ 4 วัน (ทนไม่ไหวแล้วโว้ย) เพื่อนแนะนำให้มาล้างแผลต่อที่โรงพยาบาลที่เขาทำงานอยู่เพราะน้องภัทรมีประกันโรงเรียนไม่น่าจะเกินหมื่น วันรุ่งขึ้นตัดสินใจไปเลย

ด้วยความลำบากพี่น้องเอ๋ย นั่งรถไฟมากันสามคน พ่อ แม่ ลูก (สงสารลูก กลัวเจ็บแผล) คนเยอะ ร้อน ช้า เฮ้ยยยย ทำไปได้เรา พอลงจากรถก็ตรงไปที่โรงพยาบาลทันทีตอนนั้นก็เย็นแล้ว พอเปิดแผลหน้าตาทั้งหมอทั้งพยาบาลเพื่อนช้าน แหยงๆ แล้วมาต่อว่าแม่มันว่าทำไมปล่อยให้ลูกเป็นขนาดนี้ หมอจัดการฉีดยาชากะแต่งแผลให้ใหม่ พอตัดไปได้สองทีก็บอกว่าปิดๆๆๆ มันถึงกระดูก ต้องรอหมอกระดูกอีกคนมาดู ก็รอต่อไปซักพักคุณหมอก็มา ...ที่กำไปกว่านั้น หมอขอเปิดแผลดู โอ้วแม่เจ้าโรงพยาบาลแตกอีกครั้ง สงสัยลูกจะผวาซะแล้ว พอหมอเปิดดูแป๊บเดียวก็ปิด และมาคุยกันเรื่องการรักษา ว่าจะเอายังไงดี เพราะจะต้องใช้ห้องผ่าตัด ดมยา เพื่อแต่งแผลใหม่ ก็เป็นอันตกลงละครับพี่น้อง และให้หมอทำให้ แล้วค่อย Refer ไป โรงพยาบาลรัฐ (ค่าใช้จ่ายมากมาย) หมอก็นัดให้งดอาหาร เตรียมพร้อม....ลูกแม่

วันรุ่งขึ้นพาลูกไปหาหมอตั้งแต่เช้าเลยทีเดียว เตรียมตัวเข้าห้องผ่าตัดก็ต้องตรวจสารพัดตรวจ เมื่อเรียบร้อยแล้วก็ไปรอที่ห้องผ่าตัด ใจระทึกเกิดมาไม่เคยได้มารอที่ห้องผ่าตัดแบบนี้ รู้ทั้งรู้ว่าไกลหัวใจนะ แต่ก็อดห่วงไม่ได้ เพราะต้องดมยาเด็กอายุ 5 ขวบ เวลาผ่านไป 1 ชั่วโมง ก็ยังไม่ออกมา รอแล้วรออีก ... ในที่สุดเพื่อนพยาบาลที่ได้รับอนุญาติเข้าไปออกมาบอกว่าเรียบร้อยแล้วแต่เด็กยังไม่ฟื้น ไปนอนพักที่ห้องผู้ป่วยก่อน พอลูกสาวฟื้นขึ้นมาอาการก็ยังมึนๆ อยู่ อ๊วกไป 2 รอบ ก็ดีขึ้น ค่อยโล่งใจหน่อย

วันที่สอง ทำเรื่อง Refer ไปโรงพยาบาลหาดใหญ่ (ด้วยรถส่วนตัว) พอไปถึง ER ก็บอกว่าไม่ว่างให้ไปที่ OPD ก็เข็นกันไปอีกตึกกว่าจะได้ขึ้น ward ก็เย็นแล้ว พอขึ้นไปไม่มีห้องรอไปอีก ขอบคุณน้องที่จัดการเรื่องห้องให้ ก็ได้ห้อง 532 เป็นที่เรียบร้อย เวลาผ่านไปไวเหมือนโกหก หลังจากที่กินนอนที่โรงพยาบาลเป็นเวลาเกือบเดือน ก็ได้เวลาผ่าตัดอีกรอบสำหรับนำหนังที่หน้าขามาปะที่ข้อเท้า รอบนี้เห็นสภาพลูกตนเองแล้วแทบจะร้องไห้หลังจากออกจากห้องผ่าตัดรอพักฟื้นอยู่อาการน้องเหมือนเมายาเลย น่ากลัวมาก กว่าจะปกติก็พักใหญ่

ถึงเวลากลับบ้านซักทีแผลก็เริ่มดีขึ้นแผลเย็บก็เริ่มติดแล้ว หมอนุญาตให้กลับบ้านได้ และนัดมาเป็นระยะ หลังจากนี้ก็ต้องหัดเดินซินะ เริ่มจากไม่กล้าเดิน เขย่ก เดินด้วยปลายเท้า เดินเต็มเท้าช้าๆ ตอนนี้นะเหร๋อวิ่งได้สบายมาก .... ลูกสาวคนดีของแม่

วันอาทิตย์ที่ 20 มีนาคม พ.ศ. 2554

ตัวชี้วัดที่ 4 ร้อยละของคนไข้ที่ไม่ได้รับยาปฏิชีวนะ - สืบเนื่องจากลุง

สืบเนื่องจากลุงได้ post เอาไว้ ก็เลยนำมาเขียนต่อนิดหน่อย
http://www.hospital-os.com/th/phpbb/viewtopic.php?f=5&t=3009&p=17100#p17100

ตัวชี้วัดที่ 4 ร้อยละของคนไข้ที่ไม่ได้รับยาปฏิชีวนะ จุดประสงค์ ใช้เสริมตัวชี้วัดที่ 1 ในการประเมินผลกระทบของโครงการต่อพฤติกรรมการสั่งใช้ยาหน่วยวัด ร้อยละ

สูตรคำนวณ
4.1 ร้อยละของคนไข้หวัดเจ็บคอ(J069,J00......) ที่ไม่ได้รับยาปฏิชีวนะ
      = (จำนวนคนไข้หวัดเจ็บคอที่ไม่ได้รับยาปฏิชีวนะ x 100) / จำนวนคนไข้หวัดเจ็บคอทั้งหมด (J069,J00......)

4.2 ร้อยละของคนไข้ท้องเสียเฉียบพลัน (A09) ที่ไม่ได้รับยาปฏิชีวนะ
      = (จำนวนคนไข้ท้องเสียเฉียบพลันที่ไม่ได้รับยาปฏิชีวนะ x 100) / จำนวนคนไข้ท้องเสียเฉียบพลันทั้งหมด (A09)

4.3 ร้อยละของคนไข้ที่มีแผลสะอาดที่ไม่ได้รับยาปฏิชีวนะ
      = (จำนวนคนไข้ที่มีแผลสะอาดที่ไม่ได้รับยาปฏิชีวนะ x 100) / จำนวนคนไข้ที่มีแผลสะอาดทั้งหมด

จากสูตรคำนวณข้างต้นเราต้องวิเคราะห์ข้อมูลเพิ่มเติม

1. โรคที่เราสนใจบอกได้จาก ICD10 หรือไม่และตัวไหนบ้าง
โรคที่ 1
- J069 ( UPI )
- J009 ( หวัดใหญ่)
- J028 ( คออักเสบ )
- J039 ( ทอลซิลอักเสบ )
- H71 ( หูชั้นกลางอักเสบ ร้ายแรง )
- H652 (หูชั้นกลางอักเสบ เรื้องรัง )
- H654
- J01 ( ไซนัส , โพรงจมูกอักเสบ)

โรคที่ 2 ท้องเสีย
- U6980 ( ท้องเดิน , ท้องเสีย )
- A09 ( ท้องร่วง กระเพาะสำไล้ ติดเชื้อ)

โรคที่ 3 แผล
- L89 ( แผลกดทับ )
- W26 ( ถูกมีดบาด)
- U7062 ( แผลอักเสบ )
- L984 (แผลที่ผิวหนังเรื้อรัง )
- S601 ( แผลช้ำที่เล็บ )
- T019 (แผลเปิดหลายที่ )
- S517 ( แผลที่แขน )
- O901 (แผลที่ฝีเย็บแยก)
- O900 ( แผลผ่าตัดคลอดแยก )
- K501 (แผลในช่องปาก )
- O713 (แผลฉีกขาดปากมดลูก)
- V03 ( คนเดินถูกรถยนต์ชน)
- V234 ( ขับรถเครื่องชนรถยนต์ )
- V335 ( 3 ล้อ ชนรถยนต์ )
- V499 ( อุบัติเหตุรถชน)
- V23
- V13 ( รถจักรยาน & รถยนต์ )
- V63 ( รถใหญ่)
- V031
- S433 ( การบาดเจ็บ , รับสารพิษ )

2. ยาปฏิชีวนะ คือ item ไหนบ้าง ต้องตรวจสอบตาราง r_aric_antibiotic ซึ่งเป็นตารางที่เก็บรายการยาปฏิชีวนะ

Query จากลุงชุมสินมองเรื่องค่าใช้จ่าย เมื่อได้รับยาปฏิชีวนะ

--เงื่อนไขคือ จะต้องเพิ่ม จำนวน anti biotic ในรายการ aric ก่อน

select distinct
t_visit.visit_hn
,t_visit.visit_vn
,t_visit.f_visit_type_id
,t_order.order_common_name
,t_order.order_qty || ' ' || b_item_drug_uom.item_drug_uom_description as purch
,t_order.order_price
,t_order.order_cost as cosperU
,t_order.order_qty * cast(t_order.order_cost as numeric) as cost_per_item
,t_order.order_qty * cast(t_order.order_price as numeric) as price_per_item
from t_visit left join t_order
on t_visit.t_visit_id = t_order.t_visit_id and t_order.f_order_status_id not in ('0','3')
inner join t_order_drug
on t_order.t_order_id = t_order_drug.t_order_id
inner join b_item_drug_uom
on t_order_drug.b_item_drug_uom_id_purch = b_item_drug_uom.b_item_drug_uom_id
where substr(t_visit.visit_begin_visit_time,1,10) between substr('2553-10-01',1,10) and substr('2553-10-31',1,10)
and t_visit.f_visit_status_id <> '4'
and t_visit.f_visit_type_id = '0'
and t_order.b_item_id in (select r_aric_antibiotic.b_item_id from r_aric_antibiotic);

แต่ถ้าต้องการเขียน Query รายงานตามตัวชี้วัด ดังนี้


select
--หาก diag ตามเงื่อนไข when ให้แสดงข้อความตาม then
case when t_diag_icd10.diag_icd10_number in ('J06.9','J00.9','J02.8','J03.9','H71','H65.2','H65.4','J01')
         then 'ร้อยละของคนไข้หวัดเจ็บคอ(J069,J00......) ที่ไม่ได้รับยาปฏิชีวนะ'
        when t_diag_icd10.diag_icd10_number in ('U69.80','A09')
         then 'ร้อยละของคนไข้ท้องเสียเฉียบพลัน (A09) ที่ไม่ได้รับยาปฏิชีวนะ'
        when t_diag_icd10.diag_icd10_number in ('L89','W26','U70.62','L98.4','S60.1','T01.9','S51.7','O90.1','O90.0','K50.1','O71.3','V03','V23.4','V33.5','V49.9','V23','V13','V63','V03.1','S43.3')
         then 'ร้อยละของคนไข้ที่มีแผลสะอาดที่ไม่ได้รับยาปฏิชีวนะ'
         else ''
end as disease_kpi
,count(distinct t_visit.visit_vn) as count_visit
,count(distinct case when t_order.t_order_id is null
           then t_visit.visit_vn
           else null
           end) as count_not_anti
,(count(distinct case when t_order.t_order_id is null
                               then t_visit.visit_vn
                               else null
   end) * 100) / count(distinct t_visit.visit_vn)  || '%' || as percent
from t_visit inner join t_diag_icd10
on t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn
left join t_order
on t_visit.t_visit_id = t_order.t_visit_id and t_order.f_order_status_id not in ('0','3')
       and t_order.b_item_id in (select r_aric_antibiotic.b_item_id from r_aric_antibiotic)
left join t_order_drug
on t_order.t_order_id = t_order_drug.t_order_id
left join b_item_drug_uom
on t_order_drug.b_item_drug_uom_id_purch = b_item_drug_uom.b_item_drug_uom_id
where
substr(t_visit.visit_begin_visit_time,1,10) between substr('2553-10-01',1,10) and substr('2553-12-31',1,10)
and t_visit.f_visit_status_id <> '4' and t_visit.f_visit_type_id = '0' and t_diag_icd10.diag_icd10_active = '1'
and (t_diag_icd10.diag_icd10_number in ('J06.9','J00.9','J02.8','J03.9','H71','H65.2','H65.4','J01')
       or t_diag_icd10.diag_icd10_number in ('U69.80','A09')
       or t_diag_icd10.diag_icd10_number in  ('L89','W26','U70.62','L98.4','S60.1','T01.9','S51.7','O90.1','O90.0','K50.1','O71.3','V03','V23.4','V33.5','V49.9','V23','V13','V63','V03.1','S43.3')

)
group by disease_kpi ;


อาจจะไม่ได้อธิบายมาก หากสงสัยตรงไหนก็ถามนะคะ หากไม่สงสัยก็นำไปใช้เลยละกัน  และอย่าลืมนะคะ ขอคำชี้แนะด้วยค่ะ .... โปรดติดตามตอนต่อไป -> "KPI ตาม Toward Clinical Excellence Network (TCEN) เราคงจัดการมันได้"

วันเสาร์ที่ 19 มีนาคม พ.ศ. 2554

หายหน้าหายตา

สวัสดีค่ะ หลังจากที่ไปสุ่มอยู่นาน ... นานมาก กับเวลาที่ผ่านไป จนกระทั่ง สึนามิ เข้าญี่ปุ่น จึงตื่นขึ้นมาอีกครั้ง ตอนนี้ชีวิตกำลังสับสนอาจจะสร้างผลงานออกมาได้ไม่ดีพอ แต่ไหนๆก็ตื่นขึ้นมาอีกครั้ง และเป็นสิ่งที่เป็นความตั้งใจมาตั้งแต่ไหนแต่ไร เอาล่ะ กลับมาเป็นคนเดิม ก็ดีเหมือนกัน สู้ๆ ...เอาใหม่นะคะ ตอนที่ยังมีโอกาสได้ทำอะไรที่เราเรียกว่า "ความสุข" บางทีก็คิดไม่ออกหรอกว่าจะทำอะไรก็ต้องช่วยกันจุดประกายนะ งั้นวันนนี้เริ่มจาก สืบเนื่องแล้วกันค่ะ http://www.hospital-os.com/th/phpbb/viewtopic.php?f=5&t=3009&p=17100#p17100 บังหลีของเราก็เขียนมาให้แล้วซะครึ่ง นำมาเขียนต่อก็น่าจะดีนะคะ  ...งั้นรออีกแป๊บนะซักเย็นนี้ละกันค่ะ

วันศุกร์ที่ 5 พฤศจิกายน พ.ศ. 2553

จำนวนผู้ป่วยเบาหวาน(DM)และความดัน(HT)ของสิทธิUC

สวัสดีค่ะ วันก่อนได้มีโอกาสเขียน SQL ตัวนึงค่ะ ก็เลยอยากเอามาฝากกันทุกคน
รายละเอียด คือ จำนวนผู้ป่วยนอกเบาหวานที่มีความดันร่วมด้วย โดยมีความดัน <= 130/80 เฉพาะสิทธิ UC เท่านั้น ในช่วงปีงบประมาณ 2553
มาตีความของรายละเอียดที่ต้องการก่อนดีกว่าค่ะ ว่าเขาต้องการอะไรกันแน่
1. ผู้ป่วยนอกเบาหวานที่มีความดันร่วมด้วย หมายถึง ผู้ที่มารับบริการที่ไม่มีการ Admit ด้วยโรคเบาหวาน และมีโรคความดัน จากการวินิจฉัยของแพทย์ และผู้ให้รหัส ซึ่งเราสามารถตรวจสอบจากการให้รหัส ICD-10 ได้ นั่นคือ ผู้รับบริการจะได้รับ ICD-10 ในช่วง E10-E14 (เบาหวาน) และ I10-I15 (ความดัน)
2. ความดัน <= 130/80 หมายถึง ผู้ที่มารับบริการได้วัดความดัน และความดันช่วงบนมีค่าน้อยกว่าหรือเท่ากับ 130 และ ความดันช่วงล่างต้องมีค่าน้องกว่าหรือเท่ากับ 80
3. สิทธิ UC หมายถึง ผู้มารับบริการที่ใช้สิทธิของหลักประกันสุขภาพ โดยสามารถตรวจสอบได้จาก maininscl = "WEL", "UCS", ""
4. ปีงบประมาณ 2553 หมายถึง ผู้มารับบริการในช่วงวันที่ 01 ตุลาคม 2552 ถึง 30 กันยายน 2553
สรุปตารางที่เราต้องใช้ มีดังนี้
- t_visit บอกถึงข้อมูลรับบริการในแต่ละครั้ง
- t_diag_icd10 บอกถึง รหัสที่ได้รับวินิจฉัยในการรับบริการแต่ละครั้ง
- t_visit_vital_sign บอกถึงค่าความดันที่วัดในการรับบริการ
- t_visit_payment บอกถึงสิทธิที่ผู้รับบริการใช้ในการมารับบริการแต่ละครั้ง
- b_contract_plans บอกถึงสิทธิของโรงพยาบาลว่ามีสิทธิอะไรบ้าง และเชื่อมโยงไปยังสิทธิของหลักประกันสุขภาพในสิทธิอะไร
- r_rp1853_instype บอกถึงสิทธิของหลักประกันสุขภาพ
งั้นเรามาเริ่มเขียน Query กันทีละขั้นเลยนะคะ เพื่อให้ได้ผลตามที่เราต้องการ
1. บอกว่าได้รับการวินิจฉัยเบาหานหรือความดัน
select t_visit.t_visit_id, t_visit.visit_vn, substring(t_visit.visit_begin_visit_time,1,10) ,t_diag_icd10.diag_icd10_number
from t_visit inner join t_diag_icd10
    on t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn
where t_diag_icd10.diag_icd10_active = '1' --รายการ ICD-10 ไม่ถูกยกเลิก
and t_visit.f_visit_type_id = '0' --เฉพาะผู้ป่วยนอก
and t_visit.f_visit_status_id <> '4' --รายการ visit ไม่ถูกยกเลิก
and (upper(substring(t_diag_icd10.diag_icd10_number,1,3)) between 'E10' and 'E14' --เบาหวาน
        or
        upper(substring(t_diag_icd10.diag_icd10_number,1,3)) between 'I10' and 'I15') --ความดัน
and substring(t_visit.visit_begin_visit_time,1,10) between '2552-10-01' and '2553-09-30';
2. แต่เราต้องการการวินิจฉัยเบาหวาน และความดัน จากข้อ 1 คงบอกไม่ได้เพราะอยู่คนละบรรทัด อีกทางที่เราจะทำได้ คือ มองตาราง t_diag_icd10 เป็น 2 ตารางก็ได้ ดังนี้
select t_visit.t_visit_id, t_visit.visit_vn, substring(t_visit.visit_begin_visit_time,1,10) ,icd_dm.diag_icd10_number,icd_ht.diag_icd10_number
from t_visit inner join t_diag_icd10 as icd_dm --แทนตารางเบาหวาน
    on (t_visit.t_visit_id = icd_dm.diag_icd10_vn
    and icd_dm.diag_icd10_active = '1' --รายการ ICD-10 ไม่ถูกยกเลิก
    and upper(substring(icd_dm.diag_icd10_number,1,3)) between 'E10' and 'E14' ) --เบาหวาน
 inner join t_diag_icd10 as icd_ht --แทนตารางความดัน
    on (t_visit.t_visit_id = icd_ht.diag_icd10_vn
    and icd_ht.diag_icd10_active = '1' --รายการ ICD-10 ไม่ถูกยกเลิก
    and upper(substring(icd_ht.diag_icd10_number,1,3)) between 'I10' and 'I15') --ความดัน
where t_visit.f_visit_type_id = '0' --เฉพาะผู้ป่วยนอก
and t_visit.f_visit_status_id <> '4' --รายการ visit ไม่ถูกยกเลิก
and substring(t_visit.visit_begin_visit_time,1,10) between '2552-10-01' and '2553-09-30';
3. เมื่อเราได้ผู้ป่วยเบาหวานและมีความดันร่วมด้วยแล้ว เราก็มา Focus ที่สิทธิที่รับบริการเพิ่มเติม ดังนี้

select t_visit.t_visit_id, t_visit.visit_vn, substring(t_visit.visit_begin_visit_time,1,10) ,icd_dm.diag_icd10_number,icd_ht.diag_icd10_number,r_rp1853_instype.maininscl
from t_visit inner join t_diag_icd10 as icd_dm --แทนตารางเบาหวาน
    on (t_visit.t_visit_id = icd_dm.diag_icd10_vn
    and icd_dm.diag_icd10_active = '1' --รายการ ICD-10 ไม่ถูกยกเลิก
    and upper(substring(icd_dm.diag_icd10_number,1,3)) between 'E10' and 'E14' ) --เบาหวาน
 inner join t_diag_icd10 as icd_ht --แทนตารางความดัน
    on (t_visit.t_visit_id = icd_ht.diag_icd10_vn
    and icd_ht.diag_icd10_active = '1' --รายการ ICD-10 ไม่ถูกยกเลิก
    and upper(substring(icd_ht.diag_icd10_number,1,3)) between 'I10' and 'I15') --ความดัน
inner join t_visit_payment --สิทธิที่ผู้รับบริการใช้ในการรับบริการ
   
on t_visit.t_visit_id = t_visit_payment.t_visit_id
   
and t_visit_payment.visit_payment_active = '1' --จะต้องไม่ถูกยกเลิก
inner join b_contract_plans
   
on t_visit_payment.b_contract_plans_id = b_contract_plans.b_contract_plans_id
inner join r_rp1853_instype
  
  on b_contract_plans.r_rp1853_instype_id = r_rp1853_instype.id
   
and r_rp1853_instype.maininscl in ('WEL','UCS',''--สิทธิ UC
where t_visit.f_visit_type_id = '0' --เฉพาะผู้ป่วยนอก
and t_visit.f_visit_status_id <> '4' --รายการ visit ไม่ถูกยกเลิก
and substring(t_visit.visit_begin_visit_time,1,10) between '2552-10-01' and '2553-09-30';
4. และจากโจทย์จะต้องมีความดันเช้ามาเกี่ยวข้อง เราก็ Join ตาราง t_visit_vital_sign เพิ่มเติมได้เลยค่ะ แต่ต้องวัดความดันนะคะ
select t_visit.t_visit_id, t_visit.visit_vn, substring(t_visit.visit_begin_visit_time,1,10) ,icd_dm.diag_icd10_number,icd_ht.diag_icd10_number,r_rp1853_instype.maininscl, t_visit_vital_sign.visit_vital_sign_blood_presure
from t_visit inner join t_diag_icd10 as icd_dm --แทนตารางเบาหวาน
    on (t_visit.t_visit_id = icd_dm.diag_icd10_vn
    and icd_dm.diag_icd10_active = '1' --รายการ ICD-10 ไม่ถูกยกเลิก
    and upper(substring(icd_dm.diag_icd10_number,1,3)) between 'E10' and 'E14' ) --เบาหวาน
 inner join t_diag_icd10 as icd_ht --แทนตารางความดัน
    on (t_visit.t_visit_id = icd_ht.diag_icd10_vn
    and icd_ht.diag_icd10_active = '1' --รายการ ICD-10 ไม่ถูกยกเลิก
    and upper(substring(icd_ht.diag_icd10_number,1,3)) between 'I10' and 'I15') --ความดัน
inner join t_visit_payment --สิทธิที่ผู้รับบริการใช้ในการรับบริการ
   
on t_visit.t_visit_id = t_visit_payment.t_visit_id
   
and t_visit_payment.visit_payment_active = '1' --จะต้องไม่ถูกยกเลิก
inner join b_contract_plans
   
on t_visit_payment.b_contract_plans_id = b_contract_plans.b_contract_plans_id
inner join r_rp1853_instype
  
  on b_contract_plans.r_rp1853_instype_id = r_rp1853_instype.id
   
and r_rp1853_instype.maininscl in ('WEL','UCS',''--สิทธิ UC
inner join t_visit_vital_sign
   
on t_visit.t_visit_id = t_visit_vital_sign.t_visit_id
   
and t_visit_vital_sign.visit_vital_sign_active = '1' --รายการไม่ถูกยกเลิก
   
and t_visit_vital_sign.visit_vital_sign_blood_presure <> '' --ต้องมีการวัดความดันเท่านั้น
where t_visit.f_visit_type_id = '0' --เฉพาะผู้ป่วยนอก
and t_visit.f_visit_status_id <> '4' --รายการ visit ไม่ถูกยกเลิก
and substring(t_visit.visit_begin_visit_time,1,10) between '2552-10-01' and '2553-09-30';
5. แต่ผลที่ต้องการ เราต้องการเฉพาะที่มีความดัน <= 130/80 งั้นก็มาตรวจสอบเพิ่มเติมเลยค่ะ 
select t_visit.t_visit_id, t_visit.visit_vn, substring(t_visit.visit_begin_visit_time,1,10) ,icd_dm.diag_icd10_number,icd_ht.diag_icd10_number,r_rp1853_instype.maininscl, t_visit_vital_sign.visit_vital_sign_blood_presure,cast(substring(t_visit_vital_sign.visit_vital_sign_blood_presure,1,(position('/' in t_visit_vital_sign.visit_vital_sign_blood_presure)-1)) as numeric) as bp1,cast(substring(t_visit_vital_sign.visit_vital_sign_blood_presure,(position('/' in t_visit_vital_sign.visit_vital_sign_blood_presure)+1)) as numeric) as bp2
from t_visit inner join t_diag_icd10 as icd_dm --แทนตารางเบาหวาน
    on (t_visit.t_visit_id = icd_dm.diag_icd10_vn
    and icd_dm.diag_icd10_active = '1' --รายการ ICD-10 ไม่ถูกยกเลิก
    and upper(substring(icd_dm.diag_icd10_number,1,3)) between 'E10' and 'E14' ) --เบาหวาน
 inner join t_diag_icd10 as icd_ht --แทนตารางความดัน
    on (t_visit.t_visit_id = icd_ht.diag_icd10_vn
    and icd_ht.diag_icd10_active = '1' --รายการ ICD-10 ไม่ถูกยกเลิก
    and upper(substring(icd_ht.diag_icd10_number,1,3)) between 'I10' and 'I15') --ความดัน 
inner join t_visit_payment --สิทธิที่ผู้รับบริการใช้ในการรับบริการ
   
on t_visit.t_visit_id = t_visit_payment.t_visit_id
   
and t_visit_payment.visit_payment_active = '1' จะต้องไม่ถูกยกเลิก
inner join b_contract_plans
   
on t_visit_payment.b_contract_plans_id = b_contract_plans.b_contract_plans_id
inner join r_rp1853_instype
  
  on b_contract_plans.r_rp1853_instype_id = r_rp1853_instype.id
   
and r_rp1853_instype.maininscl in ('WEL','UCS',''--สิทธิ UC
inner join t_visit_vital_sign
   
on t_visit.t_visit_id = t_visit_vital_sign.t_visit_id  
    and t_visit_vital_sign.visit_vital_sign_active = '1' --รายการไม่ถูกยกเลิก  
    and t_visit_vital_sign.visit_vital_sign_blood_presure <> '' --ต้องมีการวัดความดันเท่านั้น
where t_visit.f_visit_type_id = '0' --เฉพาะผู้ป่วยนอก
and t_visit.f_visit_status_id <> '4' --รายการ visit ไม่ถูกยกเลิก 
and cast(substring(t_visit_vital_sign.visit_vital_sign_blood_presure,1,(position('/' in t_visit_vital_sign.visit_vital_sign_blood_presure)-1)) as numeric) <= 130 --ช่วงบนน้องกว่าเท่ากับ 130
and cast(substring(t_visit_vital_sign.visit_vital_sign_blood_presure,(position('/' in t_visit_vital_sign.visit_vital_sign_blood_presure)+1)) as numeric) <= 80 --ช่วงล่างน้อยกว่าเท่ากับ 80
and substring(t_visit.visit_begin_visit_time,1,10) between '2552-10-01' and '2553-09-30';
6. หลังจากที่ได้ตามเงื่อนไขโจทย์ที่กำหนดมาแล้ว เราก็ทำส่วนสุดท้าย คือการนับยอดซึ่งตรงนี้หากนับคน เราต้องนับตาม t_patient_id และ หากต้องการนับครั้ง เราต้องนับตาม t_visit_id ซึ่งผลลัพธ์จากที่เราได้ทำ Query มานั้นอาจจะเกิดเหตุการณ์เบิ้ล Record ได้ เราสามารถนำ Distinct เข้ามาช่วยในการนับแบบไม่ซ้ำได้ ดังนี้
select count(distinct t_visit.t_patient_id) as count_pat, count(distinct t_visit.t_visit_id) as count_visit
from t_visit inner join t_diag_icd10 as icd_dm --แทนตารางเบาหวาน
    on (t_visit.t_visit_id = icd_dm.diag_icd10_vn
    and icd_dm.diag_icd10_active = '1' --รายการ ICD-10 ไม่ถูกยกเลิก
    and upper(substring(icd_dm.diag_icd10_number,1,3)) between 'E10' and 'E14' ) --เบาหวาน
 inner join t_diag_icd10 as icd_ht --แทนตารางความดัน
    on (t_visit.t_visit_id = icd_ht.diag_icd10_vn
    and icd_ht.diag_icd10_active = '1' --รายการ ICD-10 ไม่ถูกยกเลิก
    and upper(substring(icd_ht.diag_icd10_number,1,3)) between 'I10' and 'I15') --ความดัน 
inner join t_visit_payment --สิทธิที่ผู้รับบริการใช้ในการรับบริการ
   
on t_visit.t_visit_id = t_visit_payment.t_visit_id
   
and t_visit_payment.visit_payment_active = '1' จะต้องไม่ถูกยกเลิก
inner join b_contract_plans
   
on t_visit_payment.b_contract_plans_id = b_contract_plans.b_contract_plans_id
inner join r_rp1853_instype
  
  on b_contract_plans.r_rp1853_instype_id = r_rp1853_instype.id
   
and r_rp1853_instype.maininscl in ('WEL','UCS',''--สิทธิ UC
inner join t_visit_vital_sign
   
on t_visit.t_visit_id = t_visit_vital_sign.t_visit_id  
    and t_visit_vital_sign.visit_vital_sign_active = '1' --รายการไม่ถูกยกเลิก  
    and t_visit_vital_sign.visit_vital_sign_blood_presure <> '' --ต้องมีการวัดความดันเท่านั้น
where t_visit.f_visit_type_id = '0' --เฉพาะผู้ป่วยนอก
and t_visit.f_visit_status_id <> '4' --รายการ visit ไม่ถูกยกเลิก 
and cast(substring(t_visit_vital_sign.visit_vital_sign_blood_presure,1,(position('/' in t_visit_vital_sign.visit_vital_sign_blood_presure)-1)) as numeric) <= 130 --ช่วงบนน้องกว่าเท่ากับ 130
and cast(substring(t_visit_vital_sign.visit_vital_sign_blood_presure,(position('/' in t_visit_vital_sign.visit_vital_sign_blood_presure)+1)) as numeric) <= 80 --ช่วงล่างน้อยกว่าเท่ากับ 80
and substring(t_visit.visit_begin_visit_time,1,10) between '2552-10-01' and '2553-09-30';


วันศุกร์ที่ 1 ตุลาคม พ.ศ. 2553

เมื่อใช้งานจริง count มันจะยากหรือไม่น๊ะ

จากคราวที่แล้วเราก็พอทราบแล้วว่าเวลาเราจะนับนั้นใช้ Function Count และต้องใช้คู่กับการ Group By นะคะ นั่นคือ นับตามข้อมูลอะไร แต่บางทีเราก็ไม่จำเป็นต้อง Group By ก็ได้ค่ะถ้าเราไม่แสดงข้อมูลจาก Field อื่น ถ้าเช่นนั้นเรามารู้จัก Count ให้ลึกซึ้งกันดีกว่าเพื่อจะได้นำไปใช้งานได้จริง

count คือ Function สำหรับนับจำนวน record หากเรา Query ข้อมูลแล้วต้องการทราบว่า จำนวนที่เรา Query ได้มีกี่ record ก็สามารถใช้ Function นี้ได้ค่ะ แต่การใช้ count มันพิเศษกว่า นั้นค่ะ เรามาดูต่อเลยนะคะ

ควรรู้
- สามารถนับจำนวน Record ข้อมูลทั้งหมดได้
- สามารถนับจำนวน Record ข้อมูลเฉพาะที่ไม่ซ้ำกันได้
- ไม่สามารถนับค่าที่เป็น NULL ได้
- หากการ Select ข้อมูล มี filed อื่นๆ ที่ไม่ได้ใช้ count หรือ Function ประเภทเดียวกับ count ให้นำมาทำ Group By เสมอ

รูปแบบการใช้คำสั่ง
แบบที่ 1
count([ชื่อ filed]) ใช้เมื่อ ต้องการนับจำนวน record โดยที่จะต้องมีข้อมูลของ Filed ที่ใช้นับ (หากเป็น NULL จะไม่สนใจ)
แบบที่ 2
count(distinct [ชื่อ Field]) ใช้เมื่อ ต้องการนับจำนวน record โดยที่ Filed ที่ใช้นับจะต้องไม่ซ้ำกัน (โดยที่ซ้ำกันนับแต่ 1)

แนะนำตารางที่ใช้อ้างถึง
t_patient คือ ตารางเก็บข้อมูลทั่วไปของผู้ป่วยที่เคยมารับบริการ 1 คนจะมี 1 record 
t_visit คือ ตารางเก็บข้อมูลรับบริการของผู้ป่วยที่มารับบริการแต่ละครั้ง 1 ครั้งจะมี 1 Record ผู้ป่วยสามารถรับบริการได้มากกว่า 1 ครั้ง

ตัวอย่างการใช้คำสั่ง
- นับจำนวนข้อมูล visit ทั้งหมด
SELECT count(t_visit.t_visit_id) FROM t_visit WHERE t_visit.f_visit_status_id <> '4';

- นับจำนวน visit ของแต่ละวัน
SELECT substring(t_visit.visit_financial_discharge_time,1,10) as dateserv ,count(t_visit.t_visit_id) as count_visit
FROM t_visit
WHERE t_visit.f_visit_status_id <> '4'
and substring(t_visit.visit_financial_discharge_time,1,10) Between '2553-04-01' And '2553-04-30'
GROUP BY dateserv;

- นับจำนวนผู้ป่วยมารับบริการในเดือน ว่ามีกี่คน (ใน 1 เดือนอาจจะรับบริการมากกว่า 1 ครั้ง ดังนั้น Record ที่ได้จากการ Select อาจจะมากกว่าจำนวนคน)
SELECT count(distinct t_visit.t_patient_id) --ใช้ distinct เพื่อนับเป็นรายบุคคล  
FROM
t_visit
WHERE t_visit.f_visit_status_id <> '4'
and substring(t_visit.visit_financial_discharge_time,1,10) Between '2553-04-01' And '2553-04-30';

- นับจำนวนคน จำนวนครั้ง ของการมารับบริการใน Query เดียวกัน
SELECT count(distinct t_visit.t_patient_id) as count_pat --ใช้ distinct เพื่อนับเป็นรายบุคคล  
,
count(t_visit.t_visit_id) as count_visit --นับครั้งของการรับบริการ 
FROM
t_visit
WHERE t_visit.f_visit_status_id <> '4'
and substring(t_visit.visit_financial_discharge_time,1,10) Between '2553-04-01' And '2553-04-30';

มาถึงจุดเปลี่ยน ... สิ่งที่กล่าวมาข้างต้นเรื่องรูปแบบการใช้งาน นั่นคือ "ทฤษฎี" แต่เวลา "ปฏิบัติ" มันย่อมซับซ้อนกว่าเป็นธรรมดาค่ะ เรามาดูตัวอย่างที่ซับซ้อนขึ้นอีกนิดนะคะ
SELECT
count(case when t_patient.f_sex_id = '1'
    then t_patient.t_patient_id
    else NULL
 end) as man --นับเฉพาะเพศชายเท่านั้น
,count(case when t_patient.f_sex_id = '2'
    then t_patient.t_patient_id
    else NULL
 end) as women --นับเฉพาะเพศหญิงเท่านั้น
FROM t_patient;

จากตัวอย่างข้างต้นจะเห็นว่าเราไม่สามารถนับได้เลยนะคะ เราต้องมีเงื่อนไขก่อนที่จะนับซึ่งตรงนี้เราทราบคุณสมบัติของการ Count ว่าจะไม่นับค่า NULL ดังนั้น เราก็ทำให้เกิดค่า NULL ใน Record ที่เราไม่ต้องการนับโดยการขอความช่วยเหลือจาก CASE WHEN เพื่อให้สามารถนับข้อมูลได้ตรงตามจริง

งั้นมาทำความรู้จักกับ CASE WHEN คร่าวๆกันก่อนะคะ สำหรับคำสั่ง CASE WHEN จะช่วยให้เราสร้างเงื่อนไขกับข้อมูลได้ และได้มากกว่า 1 เงื่อนไข ค่ะ
รูปแบบ
CASE WHEN [ผลลัพธ์ของเงื่อนไข จริง หรือ เท็จ
         THEN [ให้แสดงหรือทำอะไรถ้า when เป็นจริง]
         WHEN [ผลลัพธ์ของเงื่อนไข จริง หรือ เท็จ]
         THEN [ให้แสดงหรือทำอะไรถ้า when เป็นจริง]
         --when คู่กับ then เสมอ แต่จะมีกี่เงื่อนไขก็ได้ มี when then กี่ตู่ก็ได้

         ELSE [ให้แสดงหรือทำอะไรถ้า when ทั้งหมดเป็นเท็จ] --จะมีหรือไม่มี else ก็ได้
END --จบ case ด้วย end เสมอ

การทำงาน
จะเริ่มจาก WHEN จะตรวจสอบเงื่อนไขเพื่อบอกว่าเราต้องการข้อมูลอะไร ซึ่งหาก WHEN ได้ข้อสรุปจากเงื่อนไขว่าเป็นจริง ก็จะทำงานตามที่ THEN สั่งการแล้วถ้าเป็น เท็จ ก็จะทำให้ ELSE แทน

งั้นเรามาทำความเข้าใจกับคำสั่งข้างต้นกันนะคะที่เอา CASE WHEN เข้ามาเป็นเงื่อนไขการนับ
โจทย์ : ต้องการนับจำนวนผู้ป่วยเพศชาย และจำนวนผู้ป่วยเพศหญิง แยกกัน 2 Field
จากโจทย์ เราก็ต้องกลับไปดูที่ข้อมูลของเราก่อนนะคะว่าจัดเก็บข้อมูลอย่างไร
t_patient คือ ตารางเก็บข้อมูลทั่วไปของผู้ป่วยที่เคยมารับบริการ 1 คนจะมี 1 record 
t_patient.f_sex_id คือ Field ที่เก็บข้อมูลรหัสเพศ โดยที่ 1=ชาย, 2=หญิง

จากข้อมูลที่เรามีลองทำทีละขั้นตอนให้เห็นที่มาที่ไปก่อนจะ Count กันนะคะ
ขั้นตอนที่ 1 : เราลอง Query ข้อมูลจากตารางนี้ดูก่อนนะคะ
คำสั่ง
SELECT t_patient.f_sex_id
FROM t_patient;
ผลลัพธ์ที่ได้
f_sex_id
1
1
2
1
2

ขั้นตอนที่ 2 : เราลองนำ CASE WHEN เข้ามาเป็นเงื่อนไขเพื่อแยกข้อมูลของเราค่ะ
คำสั่ง

SELECT
t_patient.f_sex_id
,case when t_patient.f_sex_id = '1'
    then t_patient.t_patient_id
    else NULL
 end as man --เพศชายเท่านั้น
,case when t_patient.f_sex_id = '2'
    then t_patient.t_patient_id
    else NULL
 end as women --เพศหญิงเท่านั้น
FROM t_patient;
ผลลัพธ์ที่ได้
f_sex_idmanwomen
12063096106908 NULL
12063096106910NULL
2NULL2063096104000
12063096108000NULL
2NULL2063096106911

ขั้นตอนที่ 3
: จากข้อมูลเราจะเห็นว่าจะมีค่า NULL เกิดขึ้นในกรณีที่เงื่อนไขเป็นเท็จ งั้นเราลองนับจำนวนกันดูนะคะว่าจะได้ตามที่เราต้องการหรือไม่ ชาย = 3 คน และ หญิง = 2 คน (เราต้องเอา Field
t_patient.f_sex_id ออกนะคะ เพราะไม่เช่นนั้นเราจะต้องนำมาทำ Group By ซึ่ง Output ไม่ตรงตามที่เราต้องการ เพราะตอนนี้เราต้องการให้แยก Field กันน่ะ)
คำสั่ง

SELECT
count(case when t_patient.f_sex_id = '1'
    then t_patient.t_patient_id
    else NULL
 end) as man --นับเฉพาะเพศชายเท่านั้น
,count(case when t_patient.f_sex_id = '2'
    then t_patient.t_patient_id
    else NULL
 end) as women --นับเฉพาะเพศหญิงเท่านั้น
FROM t_patient;
ผลลัพธ์ที่ได้
manwomen
32

ในทางกลับกันบางทีมันก็ง่ายกว่าที่เราทำอยู่หากโจทย์ไม่ได้ Fixed ว่าต้องการข้อมูลแบบไหนแต่ต้องการทราบว่าจำนวนเท่าไหร่ ซึ่งบางข้อมูลเราอาจจะไม่จำเป็นต้องใช้ CASE WHEN เขา้ามาช่วยเลย เพราะในข้อมูลของมันเองสามารถทำ GROUP BY และได้ผลลัพธ์เช่นเดียวกันได้ ดูตัวอย่างนับตามเพศนะคะเราก็ใช้รหัสเพศมาเป็นตัวแปรของการนับเลยค่ะ (นับตามรหัสเพศ)
คำสั่ง
SELECT
t_patient.f_sex_id
,count(t_patient.t_patient_id) as count_by_gender
FROM t_patient
GROUB BY t_patient.f_sex_id;
ผลลัพธ์ที่ได้
f_sex_idcount_by_gender
13
22

คำถามต่อไป แล้วทำไมเราต้อง COUNT(distinct ...) ด้วยล่ะ ?

อันนี้ก็เนื่องจากเราไม่รู้ว่าข้อมูลที่ JOIN มาเนี๊ยะ มีข้อมูลอะไรบ้างยังไงล่ะ หากเอา visit ไป join กับ ICD10 หรือ Order ก็อาจจะพบ record มากกว่า 1 เป็นแน่แต่โจทย์กลับบอกว่าให้นับจำนวนคน...เมื่อ Record เบิ้ล ก็จะทำให้การนับมีความผิดพลาดได้ค่ะ

งั้นเราลองมาทำโจทย์นี้ดูค่ะ แล้วจะรู้ว่าเราจำเป็นต้องใช้ Count เมื่อเรานับ "คน" "ครั้ง" ก็ด้วย
โจทย์ : ต้องการทราบจำนวนคน ครั้ง ของผู้ที่มารัับบริการ ในแต่ละเดือนของปีงบประมาณ 2553

ขั้นตอนที่ 1
: ออกแบบผลลัพธ์ที่โจทย์ต้องการ ได้ดังนี้ 
month_visitcount_patcount_visit
ตุลาคม 255220004500
พฤศจิกายน 255223405600
.........
.........
กันยายน 255322004999

ขั้นตอนที่ 2
: ตรวจสอบที่มาของข้อมูลที่จะสามารทำให้เกิดผลลัพธ์ได้ ก็ต้องดูโทย์ว่าต้องการอะไรและจาก Output เราออกแบบไว้อย่างไร ก็คงไม่พ้นตาราง t_visit แหละค่ะ เป็นตารางข้อมูลรับบริการน่ะ จะมีทั้งวันที่รับบริการ และ รหัสผู้ป่วย(t_visit.t_patient_id)ที่นับ "คน" ได้ และ รหัสการเข้ารับบริการ(t_visit.t_visit_id)ที่นับ "ครั้ง" ได้

ขั้นตอนที่ 3 : ลอง Query ข้อมูลรับบริการของปังบประมาณ 2553 ดูนะคะ
คำสั่ง
SELECT
t_visit.visit_financial_discharge_time --วันที่จำหน่ายทางการเงิน
,t_visit.t_patient_id --รหัสผู้ป่วย
,t_visit.t_visit_id --รหัสการเข้ารับบริการ
FROM t_visitWHERE t_visit.f_visit_status_id <> '4' --ข้อมูลการรับบริการไม่ถูกยกเลิก
And substring(t_visit.visit_financial_discharge_time,1,10) Between '2552-10-01' And '2553-09-30';
ผลลัพธ์ที่ได้
visit_financial_discharge_timet_patient_idt_visit_id
2553-01-19,16:49:3820600018418762555003061312
2553-01-20,17:38:0020600018418762552391103429
2553-01-22,10:30:5320600056216212554092156596
2553-01-30,13:40:5520600116668782554250372159
2553-01-30,15:30:5920600380426392553850962391

ขั้นตอนที่ 4 : จากผลลัพธ์ของขั้นตอนที่ 3 นั้นเห็นว่าข้อมูลของรหัสผู้ป่วย(t_patient_id) เป็นข้อมูลที่ซ้ำกันได้ในเดือนเดียวกัน เนื่องจาก 1 คนสามารถเข้ารับบริการได้มากกว่า 1 ครั้งนั้นเองและจากความรู้ของการ Count หากเรานับเลยจะทำให้จำนวน "คน" และ "ครั้ง" เพราะต้างก็มีข้อมูล ดังนั้น เราใช้โอกาสนี้นับแบบ Distinct คือ นับค่าที่ซ้ำกันแค่ 1 เท่านั้น และอีกส่วนหนึ่งที่เราจะสนใจ คือวันที่ค่ะ จากโจทย์เราต้องการนับเป็นเดือน จากข้อมูลของวันที่นั้นเราก็ต้องใช้วิชากันหน่อยค่ะ
คำสั่ง
SELECT
(case when substring(t_visit.visit_financial_discharge_time,6,2) = '10' --ตัดวันที่ตั้งแต่ตำแหน่งที่ 6 มา 2 ตัวจะได้เลขเดือน 2 หลัก และเทียบว่าเป็น 10 หรือไม่
        then 'ตุลาคม'  --หาก when เป็นจริง คือ เดือน 10 จะให้แสดงเป็นข้อความว่า "ตุลาคม"
        when substring(t_visit.visit_financial_discharge_time,6,2) = '11'
        then 'พฤศจิกายน'
        when substring(t_visit.visit_financial_discharge_time,6,2) = '12'
        then 'ธันวาคม'
        when substring(t_visit.visit_financial_discharge_time,6,2) = '01'
        then 'มกราคม'
        when substring(t_visit.visit_financial_discharge_time,6,2) = '02'
        then 'กุมภาพันธ์'
        when substring(t_visit.visit_financial_discharge_time,6,2) = '03'
        then 'มีนาคม'
        when substring(t_visit.visit_financial_discharge_time,6,2) = '04'
        then 'เมษายน'
        when substring(t_visit.visit_financial_discharge_time,6,2) = '05'
        then 'พฤษภาคม'
        when substring(t_visit.visit_financial_discharge_time,6,2) = '06'
        then 'มิถุนายน'
        when substring(t_visit.visit_financial_discharge_time,6,2) = '07'
        then 'กรกฎาคม'
        when substring(t_visit.visit_financial_discharge_time,6,2) = '08'
        then 'สิงหาคม'
        when substring(t_visit.visit_financial_discharge_time,6,2) = '09'
        then 'กันยายน'
 end) || ' ' || substring(t_visit.visit_financial_discharge_time,1,4) as month_visit --เมื่อได้เดือนที่เป็นข้อความแล้วให้นำมาต่อกับ ช่องว่าง และต่อด้วยเลขปีซึ่งเราตัดวันที่ในตำแหน่งที่ 1 มา 4 ตัวจะได้เลขปี พ.ศ.
,count(distinct t_visit.t_patient_id) as count_pat --นับคน
,count(t_visit.t_visit_id) as count_visit --นับครั้ง
FROM t_visitWHERE t_visit.f_visit_status_id <> '4' --ข้อมูลการรับบริการไม่ถูกยกเลิก
And substring(t_visit.visit_financial_discharge_time,1,10) Between '2552-10-01' And '2553-09-30'
GROUP BY month_visit
,substring(t_visit.visit_financial_discharge_time,1,7) --หากทำ Order By ก็ต้องนำมา Group By ด้วยนะคะ ถึงแม้จะไม่ได้แสดงก็ตาม
ORDER BY substring(t_visit.visit_financial_discharge_time,1,7); --ใช้วิชามารนิดหน่อยเพื่อให้ได้ข้อมูลที่สวยงาม

ผลลัพธ์ที่ได้ 
(ลองนำไป Query ดูนะคะ แต่ละที่จะได้ข้อมูลไม่เท่ากันค่ะ)
month_visitcount_patcount_visit
ตุลาคม 255220004500
พฤศจิกายน 255223405600
.........
.........
กันยายน 255322004999

* เท่านี้เราก็ได้ตามโจทย์ที่เราต้องการแล้วค่ะ วันนี้พอก่อนแล้วกันค่ะเด็กไม่ยอมนอนกล่อมเด็กก่อนค่ะ "ไว้ติดตามกันตอนต่อไปนะคะ"