สวัสดีค่ะ สืบเนื่องมาจากได้คุยกับคุณลุงคนหนึ่งแกเป็น เภสัชกรอยู่ที่โรงพยาบาลท่าแพ จังหวัดสตูล และเราก็คุยกันหลายเรื่องค่ะ คือเราพบว่าเรามีเป้าหมายเดียวกัน คือ อยากให้สิ่งดีๆ เกิดขึ้นในชุมชนแห่งการเรียนรู้ การแบ่งปันความรู้ และอยากให้คงอยู่ตลอดไป อันนี้ไม่ได้เกี่ยวกับอะไรทั้งนั้น เป็นเพียงกลุ่มคน กลุ่มหนึ่งที่ต้องการสร้างสรรสิ่งดีๆ และแบ่งปันกัน ก็เท่านั้นเอง
แต่สัจจธรรมก็คือ ต่างคนก็ต่างมีภาระ หน้าที่ ความรับผิดชอบ ... ใช่เราไม่ได้หมายถึง 24 ชั่วโมงของเราจะมาทุ่มเทกับสิ่งหนึ่งเพราะมันเป็นไปไม่ได้ แต่เราหาเวลาเพื่อมาทุ่มเทต่างหาก เรามีงานมีหน้าที่ เรามีครอบครัว เรามีสังคม เรามีชุมชน เราสามารถมีความสุขและทำได้ถ้าเรารู้จักความพอดี ก็บอกแล้วความสุขของคนต่างกัน ... เลือกเอาว่าจะมีความสุขแบบไหน ลองถามตัวเองว่าเคยได้รับผลตอบแทนจากการกระทำที่เป็นรอยยิ้มบ้างมั้ย ได้มองสิ่งที่เราทำแล้วอมยิ้มอยู่คนเดียว จะมีความสุขมากแค่ไหน ... ลองทำดู
เกือบจะไปบวชชีแล้ว ... แต่ก็ยังละทางโลกไม่ได้ที อิอิ
งั้นเรามาเข้าเรื่องกันดีกว่าค่ะ เพื่อให้เราทำงานง่ายขึ้นเราก็เขียนตัวช่วยมาซักตัวเอาไว้เรียกใช้กันนะคะ
สำหรับที่นำมาฝากกันวันนี้ เป็นเรื่องการหาผลต่างของเวลา ซึ่งโดยปกติ Hospital OS เก็บข้อมูลวันที่เป็น varchar ในลักษณะของปี พ.ศ. เช่น '2553-09-04,10:16:38' จะเก็บข้อมูลไว้แบบนี้ค่ะเวลาเรานำข้อมูลมาใช้งาน เราก็ต้องเข้าใจว่าข้อมูลเก็บอยู่อย่างไร
มาเล่าเรื่องวันที่กันอีกทีนะคะ ขึ้นอยู่กับว่าเรานำข้อมูลไปใช้ยังไง
สมมติข้อมูล
t_visit.visit_financial_discharge_time = '2553-04-03,01:22:24'
t_visit.visit_begin_visit_time = '2553-03-30,13:46:48'
1. เรานำไปแสดงในรายงานโดยตรง ส่วนใหญ่ผู้ใช้งานต้องการ เป็น พ.ศ. อยู่แล้ว
เราสามารถ Substring ไปได้เลยค่ะ
ใช้คำสัง -> substring(t_visit.visit_financial_discharge_time,1,10)
ผลลัพธ์ -> 2553-04-03
2. ออกแฟ้มรายงาน หรือ ส่งเข้าโปรแกรมอื่นที่ต้องการข้อมูลรูปแบบ ค.ศ.
ใช้คำสัง -> cast(substring(t_visit.visit_financial_discharge_time,1,4) as numeric) - 543 || substring(t_visit.visit_financial_discharge_time,5,6)
ผลลัพธ์ -> 2010-04-03
3. ต้องการคำนวนวันจากวันที่ การใช้ Function เกี่ยวกับวันที่นั้นโดยปกติของฐานข้อมูลจะมองข้อมูลวันที่เป็น ค.ศ. ดังนั้นหากเราต้องการได้ข้อมูลที่ถูกต้องจริงๆ เราจะต้องแปลงข้อมูลให้เป็น ค.ศ. เสียก่อน (อ้างอิงจาก ข้อ 2 ) หลังจากนั้นเราก็ค่อยนำมาใช้กับ Function อีกที ในที่นี้จะยกตัวอย่างการแปลงวันที่ เพื่อลบกันได้ นั่นคือ
3.1 เราทำการแปลวันที่สิ้นสุดก่อน ในที่นี้ขอใช้ วันที่จำหน่ายทางการเงิน
cast(substring(t_visit.visit_financial_discharge_time,1,4) as numeric) - 543 || substring(t_visit.visit_financial_discharge_time,5,6)
จะได้วันที่ในรูปแบบ ค.ศ.
หลังจากนั้นก็ cast ให้เป็นวันที่ เพื่อจะนำไปลบ โดยยกข้างต้นมาทั้งชุดเลยนะคะ
เขียน cast( as date) วางไว้ก่อนก็ได้ จากนั้น copy มาทั้งชุดมาวางหลัง วงเล็บเปิด (
จะได้
cast(cast(substring(t_visit.visit_financial_discharge_time,1,4) as numeric) - 543 || substring(t_visit.visit_financial_discharge_time,5,6) as date)
จากข้อมูลสมมติ จะได้ 3/4/2553
3.2 เราทำการแปลงวันที่เริ่มต้น ในที่นี้ขอใช้วันที่ visit
cast(substring(t_visit.visit_begin_visit_time,1,4) as numeric) - 543 || substring(t_visit.visit_begin_visit_time,5,6)
จะได้วันที่ในรูปแบบ ค.ศ.
หลังจากนั้นก็ cast ให้เป็นวันที่ เพื่อจะนำไปลบ โดยยกข้างต้นมาทั้งชุดเลยนะคะ
เขียน cast( as date) วางไว้ก่อนก็ได้ จากนั้น copy มาทั้งชุดมาวางหลัง วงเล็บเปิด (
จะได้
cast(cast(substring(t_visit.visit_begin_visit_time,1,4) as numeric) - 543 || substring(t_visit.visit_begin_visit_time,5,6) as date)
จากข้อมูลสมมติ จะได้ 30/3/2553
3.3 นำข้อ 3.1 ลบด้วย 3.2
cast(cast(substring(t_visit.visit_financial_discharge_time,1,4) as numeric) - 543 || substring(t_visit.visit_financial_discharge_time,5,6) as date)
-
cast(cast(substring(t_visit.visit_begin_visit_time,1,4) as numeric) - 543 || substring(t_visit.visit_begin_visit_time,5,6) as date)
จากข้อมูลสมมติ จะได้ 4 หน่วยเป็นวัน (วันที่ - วันที่ = จำนวนวัน)
ทีนี้เราทำแค่นี้อาจจะดูไม่ยุ่งยากนะคะ แต่ถ้าเรานำไปเขียนร่วมกับ Query ยาวแล้วอ่านจะตาลายมั้ยก็ไม่รู้ ...
ลองนำ Function นี้ไปใช้กันมั้ยคะ
function difference_datead_secs เป็น Function สำหรับหาผลต่างของวันที่และเวลา ได้ค่า วินาที ออกมาค่ะ
เริ่มต้นจากนำคำสั่งนี้ไปรัน นะคะ (รันครั้งเดียวก็พอ)
CREATE OR REPLACE FUNCTION difference_datead_secs (varchar, varchar) RETURNS int4 AS
'
declare
date_start varchar;
date_end varchar;
result_secs int;
begin
date_start = $1;
date_end = $2;
if (length(date_start) >= 10 and length(date_end) >= 10)
then
result_secs = (date_part(''day'', (cast((cast(substring(date_end,1,4) as numeric) - 543) || substring(date_end,5) as timestamp)
-
cast((cast(substring(date_start,1,4) as numeric) - 543) || substring(date_start,5) as timestamp))) * 60 * 60 * 24
+
date_part(''hour'', (cast((cast(substring(date_end,1,4) as numeric) - 543) || substring(date_end,5) as timestamp)
-
cast((cast(substring(date_start,1,4) as numeric) - 543) || substring(date_start,5) as timestamp))) * 60 * 60
+
date_part(''min'', (cast((cast(substring(date_end,1,4) as numeric) - 543) || substring(date_end,5) as timestamp)
-
cast((cast(substring(date_start,1,4) as numeric) - 543) || substring(date_start,5) as timestamp))) * 60
+
date_part(''sec'', (cast((cast(substring(date_end,1,4) as numeric) - 543) || substring(date_end,5) as timestamp)
-
cast((cast(substring(date_start,1,4) as numeric) - 543) || substring(date_start,5) as timestamp))) ) ;
else result_secs = 0;
end if;
return result_secs;
end;
'
LANGUAGE 'plpgsql';
หลังจากนั้นเวลาเรียกใช้
select
t_visit.t_patient_id
,t_visit.t_visit_id
,t_visit.visit_vn
,t_visit.visit_begin_visit_time
,t_visit.visit_financial_discharge_time
,t_visit_service.b_service_point_id
,t_visit_service.assign_date_time
,t_visit_service.visit_service_treatment_date_time
,t_visit_service.visit_service_finish_date_time
-- บรรทัดข้างล่างเป็นการเรียกใช้ โดยส่งวันที่เข้าไปไม่ต้องแปลงข้อมูลใน Function ที่เราสร้างไปแล้วนั้นจะแปลงให้เองค่ะ
,difference_datead_secs(t_visit.visit_begin_visit_time,t_visit.visit_financial_discharge_time)
from t_visit inner join t_visit_service
on t_visit.t_visit_id = t_visit_service.t_visit_id
where t_visit_service.visit_service_finish_date_time <> ''
and t_visit.f_visit_status_id <> '4'
and t_visit.f_visit_type_id = '0'
and substring(t_visit.visit_financial_discharge_time,1,10) = '2553-04-03'
order by
t_visit.t_patient_id
,t_visit.t_visit_id;
ลองดูนะคะ หากไม่เข้าใจก็ถามได้ค่ะ
โหย น้องโอ๋เขียนบทความด้านเทคนิคัลกะเขาด้วย
ตอบลบสุดยอดๆ จะลองเอาไปใช้ดู ทีหลังเขียนเรื่องทำกับข้าวแทรกด้วยก็ดีนะ จะได้หลากหลายหน่อย
ไม่ค่อยถนัดหรอกค่ะ เรื่องกับข้าว เดาเอาทั้งนั้น ... แต่ละเมนูทำครั้งแรกทั้งนั้นเลยค่ะ ... ว่าแต่ใครกันเอ่ย
ตอบลบเข้ามาอ่าน ...ฮิฮิ
ตอบลบพี่โอ๋ สุดยอดสรรสาระ และความบันเทิง
เดี๋ยวเอาไปใช้ม่าง
ว่าแต่ อ.โอ๋เขียน function เสียเป็นว่าเล่นเลย มีมั้ยที่ ไม่พอใจ functionที่เขียนแล้วต้องการจะลบ ฟังชั่นนั้นออกไปจาก postgres
ตอบลบแบบไม่เหลือเยื่อใย
อีกประเด็นที่ยังไม่รู้คือการเขียน function เข้าไปเนี้ยะทำให้ database เราโตขี้นเยอะป่าว เป็นห่วงพวก 6 gig เค้า
มีใีครคนนึงบอกมาว่าเรียนผูกก้อต้องเรียนแก้ ...งั้นก็เอาไปลบกันเลย นะคะกับคำสั่ง
ตอบลบDROP FUNCTION difference_datead_secs(varchar, varchar);
* เราต้องอ้างอิงชื่อ FUNCTION และ Parameter ที่รับให้ครบนะคะ เพราะว่าชื่อเดียวกันอาจจะรับค่าไม่เหมือนกันได้ค่ะ
ส่วนจะทำให้ database เราโตขี้นเยอะมั้ย อันนี้ไม่แน่ใจนะคะ
แต่คิดว่าไม่น่าเกียวกับการโตของฐานข้อมูลค่ะ ... เพราะเป็นแค่คำสั่ง
แต่ถ้าเกี่ยวกับการทำ backup มั้ยนั้นอาจจะเกี่ยวค่ะ ยังไงก็ต้องสร้างเหมือนกันไว้ก็ได้ master และ slave