<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-16185897</id><updated>2009-11-08T08:31:22.768+07:00</updated><title type='text'>Must Story</title><subtitle type='html'>เรื่องราวมากมาย ที่ผ่านเข้ามาในชีวิตประจำวัน</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>24</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-16185897.post-122178181826482457</id><published>2009-01-05T22:12:00.003+07:00</published><updated>2009-01-05T22:17:05.171+07:00</updated><title type='text'>Bad Man return!</title><content type='html'>คิดถึงบล็อกเกอร์เหลือเกิน ติดอยู่ตรงหา username&amp;amp;password ที่จะเข้ามาจัดการบล็อกเกอร์ไม่ได้ ไปงมหาในอีเมล์อยู่นานพอควร ในที่สุดก็หาเจอจนได้ โฮ่.................. เริ่มต้นอีกครั้งในปีวัว ๒๕๕๒ หลังจากหยุดบล็อกไปหลายเดือน .....ปี&lt;br /&gt;&lt;br /&gt;แล้วค่อยมาเล่าให้ฟังตอนหน้าครับ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-122178181826482457?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/122178181826482457/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=122178181826482457' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/122178181826482457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/122178181826482457'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2009/01/bad-man-return.html' title='Bad Man return!'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-115211932638326760</id><published>2006-07-05T23:57:00.000+07:00</published><updated>2006-07-06T00:09:17.633+07:00</updated><title type='text'>ขอหายใจให้มันโล่งหน่อยเหอะ</title><content type='html'>อืม ก็หายไปอีกเป็นเดือน จากที่มาบล็อกไว้คราก่อน จบจากเรื่องงานช้างของแม่บ้านแล้ว จะเรียกว่าจบก็ไม่เชิงเรียกได้ว่าเป็นช่วงที่พึ่งจะอัพเดทตัวโปรแกรมไปบางส่วนให้มีความปลอดภัยกับโฮสต์ที่พี่ชายท่านหนึ่งกรุณาให้พื้นที่ในการทำเวบเดโม ในฐานะที่เป็นศิษย์เก่ารังสีรามาธิบดีด้วยกันกับแม่บ้าน เชิญเข้าไปชมและทดลองใช้ได้ ที่ http://phana.dpc7.net/caixray/ ก็ต้องขอขอบพระคุณพี่ชูชาติ บรรลือ มา ณ ที่นี่ด้วยครับ&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;    เรื่องราวที่ตามเข้ามาอีกคือการขวนขวายหาที่เรียน ตัดสินใจอยู่นานว่าจะเรียนอะไร เรียนที่ไหน ในที่สุดก็ตกลงใจได้ แม้ว่าเมื่อจบมาแล้ว จะไม่มีความก้าวหน้าให้ตามที่ควรจะได้รับจากราชการ เนื่องจากสาขาที่ไปเรียนไม่ตรงตามมาตรฐานกำหนดตำแหน่งที่รับจ้างเ้ค้าอยู่ก็ตาม แต่คนเราลองว่าอยากรู้ อยากเห็นอะไรแล้ว เรื่องอื่นก็คงไม่จำเป็นเท่าไร ไม่มีทุนให้กู้ยืม ไม่มีอนาคตรอบรับ แต่ก็ดื้อที่จะเรียน ก็เพราะว่าอยากเรียน ก็แค่นี้&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;    ก็แปลกดีว่า ผมทำงานสังกัดกระทรวงสาธารณสุขมาก็นานโขอยู่ เพราะว่าอีกไม่กี่ปี หากตัดสินใจลาออกก็จะได้รับบำนาญแล้ว (แก่มาก 5555 ) เรื่องที่ผมไม่ค่อยจะเข้าใจอยู่อย่างหนึ่งคือว่า กระทรวงสาธารณสุข เป็นกระทรวงที่เป็นที่รวมของคนหลากหลายสาขาอาชีพ เช่น แพทย์, ทันตแพทย์, เภสัชกร, พยาบาล, นักวิชาการหลายแขนง เช่น นักวิชาการสาธารณสุข, นักวิชาการส่งเสริมสุขภาพ, นักวิชาการควบคุมโรค เยอะแยะไปหมด แต่มีอยู่สาขาหนึ่งซึ่งไม่มีคนที่มีความรู้ด้านนี้โดยตรงมาทำงานเลย คืองานที่เกี่ยวกับ สารสนเทศ ทั้งๆ ที่กระทรวงสาธารณสุขมีข้อมูลที่เป็นไดนามิก อยู่มากมาย พร้อมที่จะนำไปเก็บรวบรวมและแปลผลออกมาเพื่อเป็นคีย์เวอร์ด ในการทำงานทั้งในเชิงรุก และตั้งรับ จะมีอยู่ก็เพียงส่วนกลางที่เห็นๆ ก็มีอยู่ที่ศูนย์เทคโนโลยีสารสนเทศ สำนักงานปลัดกระทรวง กรมต่างๆและตามโรงพยาบาลระดับทุติยภูมิทั้งหลาย เช่น โรงพยาบาลศูนย์ หรือว่าโรงพยาบาลทั่วไป ส่วนในโรงพยาบาลที่อยู่ไกลปืนเที่ยงนั้น คงใช้บริการของเจ้าหน้าที่ที่พอจะมีความรู้เรื่องคอมพิวเตอร์ (ซึ่งอาจจะมีความชอบส่วนตัว) ทำควบคู่ไปกับงานรูทีน ตามสาขาวิชาชีพที่ได้ร่ำเรียนมา เช่นอย่างผม ซึ่งเป็นเจ้าพนักงานเภสัชกรรม หลายท่านเป็นพยาบาล หลายท่านเป็นเจ้าพนักงานสาธารณสุข เจ้าหน้าที่วิทยาศาสตร์การแพทย์ เภสัชกร เยอะแยะ สุดแล้วแต่ว่าจะหาใครได้ หรือแม้กระทั่งถ้าไม่มีใครก็ใช้บริการของแพทย์นั่นแหละ ควบคู่ไปกับการตรวจรักษาผู้ป่วย แต่ก็จ่ายเท่าเดิม ไม่มีเพิ่ม ทั้งๆ ที่ความรู้ ทักษะส่วนบุคคลเรื่องของคอมพิวเตอร์เนี่ย ในความรู้สึกส่วนตัวของผมมันน่าจะมีค่าตอบแทนเพิ่มบ้าง เพราะต้องขวนขวาย ใฝ่รู้ ค้น เสาะ แสวงหา เพื่อได้คำตอบสักคำตอบที่อาจมีแค่ประโยคสักประโยคนึง ที่ร้ายไปกว่านั้น บางท่านทำเรื่องคอมพิวเตอร์เป็นงานหลักซะด้วยซ้ำไป เนื่องจากมีความสามารถ รอบรู้ แต่พอถึงเวลาประเมินผลงานเพื่อปรับระดับขึ้นตามสายงานเดิม กลับนำผลงานที่ทำเกี่ยวกับคอมพิวเตอร์มาขอประเมินไม่ได้ ทาง อ. กพ. (คณะอนุกรรมการข้าราชการพลเรือนประจำจังหวัด) ไม่เห็นด้วยเนื่องจากลักษณะงานที่ทำไม่สอดคล้องกับมาตรฐานกำหนดตำแหน่ง แล้วคนที่เจ็บคือใคร คือเขาคนนั้น (ไม่ใช่ผมแน่นอน แต่ก็ใกล้เคียง) ก็เลยขอกลับไปทำงานตามสายงานเดิมที่ดำรงตำแหน่งอยู่ เพื่อทำผลงานวิชาการเสนอขอเลื่อนระดับกับเค้า อ้าว แล้วใครจะมาทำงานต่อลื้อฟะ ผู้บริหารก็ย้อนถาม ก็ไม่มีคำตอบทั้งผู้ถูกถาม และไม่มีคำพูดต่อจากผู้ถาม งานก็สะดุดเดินต่อไม่ได้ สถานการณ์นี้คงฟันธงไปไม่ได้่ว่าใครผิด ใครถูก คนไหน หรือว่าระบบราชการ&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;    ผมเคยคุยกับน้องที่เรียนมาทาง Computer Science, Computer Engineer ว่าทำไมไม่สนใจจะเข้าไปทำงานในฟิลด์ของสาธารณสุขบ้าง ก็ได้รับคำตอบที่รับฟังแล้ว ก็อึ้งไป น้องบอกว่าค่าตอบแทนต่ำเกินไป สำหรับมาตรฐานงานของเค้า แถมยังมีกฏ ระเบียบ ให้จุกจิกกวนใจอีก อือ คงจะจริงระบบงานของราชการ ไม่ค่อยเอื้ออำนวยให้การทำงานลักษณะนี้มากนัก ผมเคยได้ยินประกาศรับสมัครงานของโรงพยาบาลของรัฐแห่งหนึ่งใกล้ๆ บ้าน รับสมัครเจ้าหน้าที่ระบบคอมพิวเตอร์ มีหน้าที่ ................. ตั้งแต่ดูแล ฮาร์ดแวร์ เขียนโปรแกรม ดูแล บำรุงรักษาระบบเครือข่าย แล้วที่น่าสนใจก็คือ เงินเดือนเพียง x,xxx บาท (ไม่ถึงหมื่น) ก็นึกอยู่ในใจว่า ใครจะมาสมัครฟระ ทำซะป๊ะ ได้แค่เนี๊ยะ ทำงานบริษัทได้ต่ำๆ ก็เป็นหมื่น แถมยังทำงานเฉพาะด้าน ไม่จับฉ่าย ขั้นตอนการเบิกจ่ายค่า่ล่วงเวลาก็ไม่ยุ่งยาก สวัสดิการก็ไม่น้อยกว่าข้าราชการแล้ว&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;    ออกมาบ่นซะมาก คับแค้นใจที่การประสานงานในระดับสูง (กระทรวง และ ก.พ.) เป็นไปอย่างเชื่องช้า เต็มไปด้วยความกลัว กลัวซึ่งการสูญเสียอำนาจ สำนักงานคณะกรรมการข้าราชการพลเรือน หรือที่เรียกกันย่อๆ ว่า กพ. นั้น ปัจจุบันมีข้าราชการในสังกัดส่วนมากเป็นข้าราชการในกระทรวงสาธารณสุข ซึ่งหากว่ากระทรวงสาธารณสุขขอแยกตัวออกไปมีคณะกรรมการเองแล้วนั้น จะเหลือข้าราชการที่อยู่ในสังกัด กพ. ไม่ถึงครึ่ง แล้วอะไรจะเกิดขึ้น เหล่านี้เป็นตัวอย่างของ ระบบราชการที่ผมคิดว่าควรที่จะได้รับการรี...... รีรีให้มันเกิดประโยชน์ ทั้งกับราชการ ทั้งจูงใจให้คนที่มีความรู้ ความสามารถ ได้เข้ามาทำงาน จริงอยู่ว่าตอนนี้คนอยากทำงานมีเยอะ แต่คนเราต้องกินข้าว ทุกคนย่อมมีสิทธิเลือกทางเิดินที่คิดว่ามันคุ้มค่ากับตัวเอง งานสองแห่งทำเหมือนกัน ผมว่าคงไม่มีคนเลือกทำงานกับองค์กรที่จ่ายน้อยกว่าแน่นอน เป็นผมผมก็คิดอย่างนั้นเหมือนกัน&lt;br /&gt;&lt;hr&gt;   &lt;br /&gt;    รู้สึกว่าการได้ออกมาพูด ถึงสิ่งที่มันคับคั่งในใจออกไปซะบ้างก็ทำให้หายใจสะดวกขึ้น โล่ง ถึงแม้ว่าพรุ่งนี้จะต้องกลับไปทำงานในสภาพเดิมๆ อีกซ้ำแล้ว ซ้ำอีก ก็ตาม แต่ก็ทำ เพียงเพราะว่าอยากทำอะไร เพื่อพ่อหลวงของเราบ้าง ให้สมกับที่ท่านทรงงานหนักเพื่อพสกนิกรชาวไทยมาหลายสิบปี เป็นการตอบแทนที่ควรจะทำเป็นอย่างยิ่ง ในวาระที่ปีนี้พระองค์ท่านทรงครองราชย์มาเป็นระยะเวลาถึง 60 ปี เพียงเพราะอยากให้ราษฏรชาวไทยได้อยู่ดี กินดี อยู่อย่างพอเพียง จากน้ำพระทัยที่เปี่ยมล้นด้วยพระเมตตาอันหาที่สุดมิได้ นับเป็นบุญ วาสนาของผม และครอบครัวที่ได้เกิดมาใต้ร่มพระบรมโพธิสมภารอันร่มเย็นแห่งนี้ภายใต้ผืนแผ่นดินไทย.&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;    &lt;span style="font-weight: bold;"&gt;ขอจงทรงพระเจริญ ด้วยเกล้าด้วยกระหม่อม ขอเดชะ ข้าพระพุทธเจ้า นายอุทัย เลือดนักรบ พร้อมครอบครัว ขอถวายพระพร&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-115211932638326760?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/115211932638326760/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=115211932638326760' title='3 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/115211932638326760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/115211932638326760'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2006/07/blog-post.html' title='ขอหายใจให้มันโล่งหน่อยเหอะ'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-114795424854590591</id><published>2006-05-18T19:07:00.000+07:00</published><updated>2006-05-18T19:10:48.560+07:00</updated><title type='text'>งานช้าง</title><content type='html'>หายไปนานกับการเขียนบล็อก นานมากด้วยนะ เรื่องราวที่เกิดขึ้นในช่วง 2-3 เดือนที่ผ่านมาเป็นเรื่องราวของคนใกล้ตัว เหอ เหอ คือคนที่อยู่กินด้วยกัน มีลูกด้วยกันนั่นแล&lt;br /&gt;    โจทย์ของเขาคนนั้น คือทำงานอะไรสักอย่างที่เกี่ยวข้องกับรังสีการแพทย์ ไม่จำกัดว่าจะเป็นอะไร ขอให้เป็นงานที่เอาไปใช้แล้วเกิดประโยชน์ มองดูแล้วเป็นของใหม่ ซึ่งไม่ได้ลอกเลียนเขามา เช่นทำอุปกรณ์ช่วยในการจัดท่าเอกซเรย์ หรือ ทำวิจัยเรื่องเกียวกับรังสี ทำอะไรก็ได้่ว่างั้น&lt;br /&gt;    ก็มานั่งคุยกัน แฟนผมก็อยากทำเกี่ยวกับการสอน เหตุจูงใจก็มาจาก เมื่อก่อนตอนที่ยังอยู่บ้านพัก ก็ต้องอยู่เวรนอกเวลา เวลามีเคสนอกเวลาก็ขึ้นไปทำเอง ปัญหาเกี่ยวกับเทคนิคการฉายรังสีก็ไม่เกิด ทีนี้พอมาอยู่บ้านตัวเอง ก็ไม่ได้อยู่เวรแล้ว เป็นน้องๆ ที่แฟน เค้าเทรนขึ้นมาเพื่อที่จะปฏิบัติงานแทนในเวลาที่ไม่ได้มาทำงาน หรือไปอบรม ไปราชการ ตอนแรกๆ ก็ราบรื่นดีอยู่หรอก ช่วงหลังๆ มา แพทย์เวรมักสั่งให้เอกซเรย์ท่าแปลกๆ ใหม่ๆ น้องที่อยู่เวรก็ไม่ชัวร์ว่าัจะจัดท่าอย่างไร ใช้อุปกรณ์อย่างไร ต้องโทรมาถามให้แน่ใจ กว่าจะลงมือทำได้ก็เนิ่นนาน คิดไปก็บ่นไปว่าทำอย่างไรจะให้น้องๆ เค้ามีคู่มือเกี่ยวกับเทคนิคง่ายๆ ประกอบการใช้งาน นอกจากหนังสือ,แผ่นป้ายที่ได้รับจากบริษัทขายอุปกรณ์ เพื่อที่จะเห็นว่าจัดท่าอย่างไร ใช้ปริมาณรังสีเท่าไร ฟิล์มที่ได้ควรเป็นอย่างไร เครื่องคอมพิวเตอร์ในที่ทำงานก็มีว่างอยู่ น่าจะเอามาทำประโยชน์ตรงนี้ได้&lt;br /&gt;    ทบทวนอยู่หลายรอบแล้วมีความเห็นตรงกันว่าจะทำเป็น บทเรียนช่วยสอน (Computer Assisted Instruction) แต่ว่าจะทำอย่างไรล่ะ ใช้เครื่องไม้เครื่องมือตัวไหนมาพัฒนา นึกไปถึง Authorware ซึ่งผมเองเคยไปอบรมมาเมื่อหลายปีก่อน (หลายปีมากๆ แล้ว) คิดว่าพอจะรื้อฟื้นไหวน่า&lt;br /&gt;    แต่แฟนผมกลับมีโจทย์เพิ่มเติมมาอีกว่า เมื่อทำเป็น CAI แล้ว ควรที่จะให้ผู้ใช้ เพิ่มเติม แก้ไข ข้อมูลเหล่านั้นด้วยตัวเองได้ด้วย อืม Authorware มันจะทำได้ป่าวฟระ เริ่มคิดอยู่หลายตลบ หนักใจมากขึ้น คิดถึง Web Application ขึ้นมาตะหงิดๆ&lt;br /&gt;    Web Application เป็นคำตอบที่ชัดเจนในโจทย์นี้ สามารถโต้ตอบกับยูสเซอร์ได้แน่ๆ แต่การ implement ระบบนั้นหิน ต้องมีเวบเซอร์เวอร์ มีฐานข้อมูล โอวพระเจ้าจอร์ช แค่คิดก็เหนื่อยแ้ล้ว ลำพังแค่การเขียนเวบเพจเพื่อติดต่อฐานข้อมูล ก็ยากอยู่แล้ว (ผมเรียนมาทางวิทยาศาสตร์สุขภาพ) งานการที่ทำอยู่ทุกวันก็ให้บริการผู้ป่วย ไม่ได้ร่ำเรียนมาโดยตรงในด้านวิทยาการคอมพิวเตอร์ นึกๆ แล้วก็ค่อนข้างท้อ&lt;br /&gt;    พักเรื่องนี้ไปหลายวัน ขณะนั้นก็ไซโคแฟนไปเรื่อย ให้เปลี่ยนโปรเจ็คซะดีกว่า งานนี้ยากทั้งคนทำ ยากทั้งคนเอาไปใช้ เล่นเอาซึมไปทั้งคนฟัง และคนพูด&lt;br /&gt;    แวบนึงที่ผุดขึ้นมาในสมอง คือ AppServ 3 in 1 ทั้ง Apache, MySQL, PHP การติดตั้งก็ไม่ยากมาก Next Next ... แล้วก็ Finish ตามสไตล์ของหน้าต่าง ใช้บนหน้าต่างได้ กลุ่มที่เซียนหน่อย (ใช้ลินุกซ์เป็น) ก็เอาแค่เวบเพจไปวางที่เวบรูท ส่วนการสร้างฐานข้อมูลก็ไม่น่าเป็นปัญหา อืม เริ่มมีความหวังมาบ้าง กลับมาคุยกันอีกครั้งกับแฟน ว่าเอางัยดี ยังพอรับไอเดียนี้ได้ปะ ถ้าตกลงก็จะได้เริ่มลงมือทำงาน ถ้าคิดว่ามันดูไม่เวอร์คก็จะได้ช่วยหาข้อมูลทำโปรเจ็คอื่นๆ ให้ คำตอบก็อ่อยๆ ว่าตอนนี้ยังคิดไม่ตก พอจะทำให้ดูก่อนได้ไหม&lt;br /&gt;    ตัดสินใจว่าจะลองทำเป็นเดโมให้ดูก่อน ว่ามันพอจะเป็นโปรเจ็คสำหรับการไปนำเสนอเพื่อจบการเรียนได้ไหม สรุปแล้วก็มีอะไรที่เกี่ยวข้องดังนี้เอง&lt;br /&gt;    1. AppServ&lt;br /&gt;    2. เวบเพจที่เขียนด้วย html, PHP, Javascript&lt;br /&gt;    ใช้เวลาอยู่พอสมควรในการออกแบบฐานข้อมูล, ภาพรวมของระบบทั้งหมด, หาข้อมูล ตลอดจนสคริปต์ของ php ที่น่าจะเอามาประยุกต์ใช้ได้จากอินเทอร์เน็ต ได้หน้าเวบเพจมาสองเพจ 5555 อย่างที่บอกครับ ว่าคนที่ไม่เคยทำอะไรเกี่ยวกับการเขียนโปรแกรมเนี่ย ไอเดียกระฉูดก็จริง แต่พอลงมือทำแล้วมันก็ติด ก็ไปค้นหาคำตอบจากอินเทอร์เน็ตบ้าง ถามคนที่เค้าหากินกับเวบบ้าง กว่าจะสรุปแล้วทำเป็นเวบเพจสองเพจเนี่ย มันยาก แต่ก็น่าชื่นใจที่มาถูกทาง สรุปเป็นคำตอบสุดท้ายได้ว่าใช่&lt;br /&gt;    ลงมือทำงานอย่างจริงๆ จัง เปลี่ยนเวลาทำงานจากการนอนดึก เป็นการเข้านอนแต่หัวค่ำ ตื่นมาตอนตีสอง นั่งโค๊ดไปด้วย หาข้อมูลไปด้วย อากาศในช่วงนั้นก็เริ่มร้อน บางทีก็หยุดเนื่องจากติด ต้องค้นหาวิธีการแก้ปัญหา ประกอบกับเจ้าของโปรเจ็คไปฝึกงานที่ในเมืองหลวง ไม่ได้อยู่ช่วยกันเตรียมข้อมูลพื้นฐานบางส่วนให้ เลยทำให้งานไปได้ช้า ช่วงนี้เริ่มเครียด concept ของโปรแกรมมันก็ไม่ได้มีอะไรที่หวือหวา เรื่องที่ไม่คิดว่าจะยาก แต่ทำให้ใช้เวลานานคือ การที่เราต้องเขียนโปรแกรมเกี่ยวกับฐานข้อมูล ต้องมี Insert, Update, Delete ตรงนี้ต่างหากที่เป็น Critical ผนวกกับเราไม่มีประสบการณ์เกี่ยวกับการโค๊ดโปรแกรม Logic ในบางจุดเราหาทางออกไม่ถูกทาง ก็ต้องกลับมาทบทวนใหม่ โชคดีที่ยังมีที่ปรึกษาที่ดีมากๆ จากทีมงาน iMed คือ กวงกะเหน่ง สองโปร คอยให้คำแนะนำว่าึควรจะทำในลักษณะไหน ค้นหาข้อมูลเพิ่มเติม&lt;br /&gt;    ประมาณกลางเดือนเมษายน เดือนที่ร้อนที่สุด และเป็นเดือนที่มีวันหยุดต่อเนื่องยาว ก็เปิดตัว alpha ได้ ท่ามกลางความกังขาของทั้งสองคน ผัวเมีย ว่ามันจะไปรอดอะป่าว เหอ เหอ แต่เราก็มาไกลเกินกว่าจะหยุดได้ซะแล้ว อีกอาทิตย์ต่อมา ตัว beta ก็คลอด ตามมาติดๆ ด้วย preview release, release candidate1 ...... 10 กว่าๆ ภายในระยะเวลาไม่กี่วัน พร้อมกับคู่มือการติดตั้ง, การใช้งาน ทั้งหมด เตรียมพร้อมสำหรับทำเป็นรูปเล่มได้&lt;br /&gt;    ต้นเดือน พฤษภาคม ทดสอบบนหน้าต่างใช้งานได้ไม่มีปัญหา แต่พอมาลองทดสอบบน ลินุกซ์ อ้าว ติดขัดเต็มไปหมด ต้องกลับมารีวิวใหม่อีกรอบ ต้องถอยกลับมาเป็น beta อีกครั้ง ทีนี้เริ่มทำงานได้เร็วมากขึ้นกว่าเดิม โค๊ดที่ดูว่ามันบ้านนอก ก็ปรับแก้ไปแล้วบางส่วน (เฉพาะส่วนที่เจอ) ในที่สุดก็สามารถทำให้โปรแกรมใช้งานบนลินุกซ์เซอร์เวอร์ได้ แต่ฐานข้อมูลยังมีการอัพเดทไปเรื่อยๆ พร้อมกับคู่มือที่เขียนใหม่อย่างเร่งด่วนซะเหลือเกิน&lt;br /&gt;    วันที่ 10 พฤษภาคม 2549 เป็นวันที่ปิดงานในเฟสแรก (Stable) คิดว่าจะทำให้มันนิ่ง นิ่งเฉพาะในส่วนของโค๊ด แต่ในส่วนของฐานข้อมูลยังคงมีการอัพเดทอยู่เรื่อย สืบเนื่องมาจากตอนนี้ แฟนกลับมา แล้วเอางานไปนำเสนออาจารย์ที่ปรึกษาแล้ว ก็มีงานที่ต้องปรับปรุงอีกในส่วนของรูปการจัดท่าและ คำอธิบาย&lt;br /&gt;    ตอนนี้ผมอัพโหลดไฟล์ไว้ที่ Hospital-os dot com แล้ว นำเสนอกับชุมชน เพื่อหา Feedback นำไปปรับปรุงโปรแกรมให้เหมาะสมในการใช้งาน ง่ายในการดูแล ไม่รบกวนเวบเซอร์เวอร์&lt;br /&gt;    ไฟล์ที่นำเสนอมีอยู่ด้วยกันสองส่วนคือ&lt;br /&gt;    1. Win32 Plateform มีไฟล์ที่จำเป็นอยู่สองสามไฟล์คือ&lt;br /&gt;        1.1 appserv-win32-2.4.4a.exe&lt;br /&gt;        1.2 appserv-AddOns-ZendOptimizer-2.5.10.exe&lt;br /&gt;        1.3 AppServProjectXAddOns_stable_1.0_11052006.exe (ผมทำเป็น Appserv Addons ไว้เพื่อให้ยูสเซอร์ติดตั้งง่ายที่สุด)&lt;br /&gt;    ซึ่งไฟล์ตามข้อ 1.1, 1.2 ดาวน์โหลดได้ที่ไซต์ของ appservnetwork โดยตรงเลยนะครับ&lt;br /&gt;        1.4 ส่วน projectx-addons ก็ดาวน์โหลดได้ที่ home ของผมผ่าน http://www.hospital-os.com/~uthai/Download/phpCaiXray/win32/AppServProjectXAddOns_stable_1.0_11052006.exe&lt;br /&gt;        1.5 md5 ของไฟล์ข้างต้นคือ 7d236df57c2ef7daa9d84eadf2e281d2&lt;br /&gt;        1.6 สำหรับคู่มือก็ดาวน์โหลดได้ที่ http://www.hospital-os.com/~uthai/Download/phpCaiXray/win32/handbook.zip อ่านให้ละเอียดนิดนึงนะครับ&lt;br /&gt;    2. Linux Platform&lt;br /&gt;        2.1 ไฟล์ www.hospital-os.com/~uthai/Download/phpCaiXray/linux/phpCaiXray.zip&lt;br /&gt;        2.2 MD5 ก็ดาวน์โหลดไฟล์นี้ไป www.hospital-os.com/~uthai/Download/phpCaiXray/linux/phpCaiXray.md5&lt;br /&gt;        2.3 การติดตั้งก็อ่านได้จากไฟล์ www.hospital-os.com/~uthai/Download/phpCaiXray/linux/howto.txt&lt;br /&gt;ยาวมากไปแล้ว ไว้ต่อคราวหน้าแล้วกัน&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-114795424854590591?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/114795424854590591/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=114795424854590591' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/114795424854590591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/114795424854590591'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2006/05/blog-post.html' title='งานช้าง'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-113837450720051533</id><published>2006-01-27T22:02:00.000+07:00</published><updated>2006-01-27T22:08:27.213+07:00</updated><title type='text'>Hi Speed Internet กับความฝัน</title><content type='html'>หลังจากที่หงุดหงิดมานานเกี่ยวกับ การเชื่อมต่ออินเทอร์เน็ตที่บ้านจากที่เคยใช้โมเด็ม 56K ผ่านเน็ตเวอร์คของสำนักงานสาธารณสุขจังหวัดลำพูน ซึ่งก็คอนเน็คได้บ้างไม่ได้บ้าง ดูเว็บได้บ้าง ช้าบ้าง ไม่อยากพูดเรื่อง apt-get เลยอายชาวบ้านเค้า พอๆกับแก้กางเกงแล้วโชว์ตูดให้ดูนั่นแหละ อยู่มาวันหนึ่งก็เลยคุยกันในครอบครัว ความจริงก็คือ ผมกับเมีย (คือผู้หญิงที่เป็นแม่ของลูกผม ซึ่งอยู่กินด้วยกันทุกวันนี้) ว่าเราน่าจะหาอินเทอร์เน็ตความเร็วสูงมาใช้กันบ้างนะ บ้านเราก็อยู่ในพื้นที่ให้บริการอยู่ เหอะๆ ง่ายกว่าที่คิดแฮะ แต่ก็ต้องแลกเปลี่ยนกับการใช้โทรศัพท์แบบ Post paid มาเป็นแบบเติมเงิน เพื่อหมุนเวียนการใช้เงินค่าโทรศัพท์ให้เกิดประโยชน์มากที่สุด เออ ค่อยยังชั่วหน่อยนึกว่าเงื่อนไขจะซับซ้อน ได้ๆ เรื่องนี้จัดให้ พอติดต่อกับ TT&amp;T จนกระทั่งใช้ได้จนถึงทุกวันนี้รู้สึกว่ามีความสุขในการใช้อินเทอร์เน็ตมากขึ้นไม่ว่าจะเป็นการ search ข้อมูลให้เมีย apt-get ให้ตัวเอง ดาวน์โหลด iso ซีดีของลินุกซ์ดิสโทรที่สนใจ โอยพึ่งรู้ว่ามันแฮปปี้จริงๆ แต่รู้สึกว่ายังไม่คุ้มเท่าไหร่เนื่องจากว่าตอนกลางวันก็ไปทำงานกว่าจะกลับมาใช้อินเทอร์เน็ตอีกทีก็ปาเข้าไปสาม สี่ทุ่มไปแล้ว เคยคุยกับเพื่อนๆ เค้าบอกว่าอย่าให้เสียเวลาเด่ โหลตบิตมาเบอร์นลงแผ่นขายดิ๊  ในเน็ตประเภทปลุกใจเสือป่ามีเยอะ บ้านมึงก็บ้านนอก คงไม่มีคนใช้ Hi Speed Internet กันทุกหลังคาเรือนหรอกวะ เบอร์นลงแผ่นขายเอาเงินมาจ่ายค่าเน็ตเดือนละ สอง สามร้อยก็ดี ดีกว่ามึงจ่ายเองนา เออไอ้นี่ไอเดียจ๊าบว่ะ แต่กรูน่ะ เสี่ยงคุกเสี่ยงตาราง แถมไม่พอยังถูกตราหน้าว่าเป็นคนลามกจกเปตรอีก ความคิดนี้คงไม่เอาด้วยแน่ๆ  แต่ที่คิดๆ ไว้ตอนนี้ที่อยากทำคือ&lt;br /&gt;1. อยากจะลองลงเดเบียนแบบใช้ debootstrap ดูกะเค้าสักทีจะได้มีความรู้เกี่ยวกับเดเบียนขึ้นอีกหลังจากที่เคยลองครั้งหนึ่งแล้วพักไปเนื่องจากเน็ตเร็วไม่พอ&lt;br /&gt;2.อยากจะลองลง gentoo ดูอีกครั้ง เพราะรู้สึกว่าการลง gentoo ทำให้ได้ความรู้เกี่ยวกับลินุกซ์เยอะมาก ครั้งก่อนก็เคยลองแต่ไม่สำเร็จเหตุผลเดียวกับข้อแรก&lt;br /&gt;3.ค้นหาข้อมูลและซอพท์แวร์เกี่ยวกับ Business Intelligence สืบเนื่องมาจากไป TMI มาแล้วไปชมการสาธิต iAnalysis (เป็นโปรเจ็กต์ของบริษัทโอเพ่นซอร์สเทคโนโลยี คือบริษัทที่พัฒนา Hospital OS นั่นแหละ เพียงแต่ว่าตัว iAnalysis เนี่ยไม่ใช่ Opensource) ไปค้นหาอยู่นานก็มาจบที่ Mondrian ซึ่งเป็น OLAP Server อยู่ก็เลยจะพยายามแกะเอามาใช้ร่วมกับ PostgreSQL อาจจะเป็นประโยชน์กับหน่วยงานที่เราทำงานอยู่ ฐานข้อมูลของโรงพยาบาลก็มีแล้ว หากทำได้ตรงนี้ ก็อาจจะทำเป็นโซลูชั่นเอาไปเสนอขายให้กับ โรงพยาบาลอื่นๆ อาจจะได้ขาย แล้วก็จะได้เงิน เอามาจ่ายค่าเน็ต ความรู้ก็ได้ เงินก็ได้ ไม่ต้องเสี่ยงคุก เสี่ยงตารางด้วย เอาตามนี้แล้วกัน แต่ทำไมมันยากอย่างนี้ แกะมาเป็นเดือนยังไม่ก้าวหน้าเลย เฮ้อ รู้สึกว่าเงินทองมันหายากจริงๆ ท่านใดที่เคยใช้ และมีประสบการณ์เกี่ยวกับ Mondrian ก็ขอความรู้บ้างนะครับ สนับสนุนการศึกษาผู้ใหญ่&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-113837450720051533?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/113837450720051533/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=113837450720051533' title='5 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113837450720051533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113837450720051533'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2006/01/hi-speed-internet.html' title='Hi Speed Internet กับความฝัน'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-113518693029828571</id><published>2005-12-22T00:37:00.000+07:00</published><updated>2005-12-22T00:42:10.313+07:00</updated><title type='text'>ต้นตอของปัญหา</title><content type='html'>ในที่สุดก็ค้นหาคำตอบจนได้ว่าทำไม &lt;a href=http://www.postgresql.org&gt;PostgreSQL&lt;/a&gt; 8.0.3 ที่คอมไพล์เองบนเครื่องที่เอาไว้ทำเป็นมิเรอร์ถึงไม่สนับสนุนเรื่อง multibyte ก็เป็นเรื่องที่คาใจมาตลอดระยะเวลาหลายสัปดาห์ ว่าทำไม ....&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;ขอย้อนกลับไปนิดนึงว่าปัญหาที่เกิดขึ้นเป็นอย่างไร&lt;br&gt;&lt;br /&gt;&lt;pre class=box&gt;&lt;br /&gt;postgres@phoenix:/etc/postgresql/8.1/main$ psql reportdb_v3&lt;br /&gt;Welcome to psql 8.1.0, the PostgreSQL interactive terminal.&lt;br /&gt;&lt;br /&gt;Type:  \copyright for distribution terms&lt;br /&gt;       \h for help with SQL commands&lt;br /&gt;       \? for help with psql commands&lt;br /&gt;       \g or terminate with semicolon to execute query&lt;br /&gt;       \q to quit&lt;br /&gt;&lt;br /&gt;reportdb_v3=# select item_common_name From b_item where LOWER(item_common_nam e) LIKE '%cpm%';&lt;br /&gt;        item_common_name&lt;br /&gt;---------------------------------&lt;br /&gt; CPM  .-inj  ( 10 mg./ml. ) *&lt;br /&gt; CPM  .-tab  ( 4 mg. )*&lt;br /&gt; CPM  .-Syr  (2mg./5ml.) - 60ml.&lt;br /&gt; CPM hand&lt;br /&gt; CPM Elbow&lt;br /&gt; CPM&lt;br /&gt;(6 rows)&lt;br /&gt;&lt;br /&gt;reportdb_v3=# select item_common_name From b_item where UPPER(item_common_nam e) LIKE '%cpm%';&lt;br /&gt;ERROR:  invalid multibyte character for locale&lt;br /&gt;reportdb_v3=#&lt;/pre&gt;&lt;br /&gt;และเมื่อลองดูตัวแปรที่เกี่ยวข้องก็ได้ตามนี้&lt;br /&gt;&lt;pre class=box&gt;&lt;br /&gt;postgres@phoenix:/etc/postgresql/8.1/main$ cat /etc/environment&lt;br /&gt;LANGUAGE="en_TH:en_US:en_GB:en"&lt;br /&gt;&lt;br /&gt;LANG=en_US.UTF-8&lt;/pre&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;ไปค้นดูใน&lt;a href=http://www.google.com&gt; กูเกิล&lt;/a&gt; ด้วย keyword error+multibyte+locale site:postgresql.org ก็พบว่ามีคนเคยเจอเหมือนเรา &lt;a href=http://archives.postgresql.org/pgsql-bugs/2005-11/msg00275.php&gt; ที่นี่ &lt;/a&gt;วิธีการแก้ปัญหาของเค้าคือ&lt;br /&gt;&lt;ol&gt;&lt;br /&gt; &lt;li&gt;ก่อนทำการคอมไพล์ Postgres ให้ export LANG=en_US.UTF-8 ซะก่อน แล้วค่อยทำการ ./configure ; make ;make install ไปตามลำดับ&lt;/li&gt;&lt;br /&gt; &lt;li&gt;ต่อเมื่อจะ initialize database ให้เพิ่ม option --locale=C ไปด้วย&lt;br /&gt; For Example&lt;br /&gt; &lt;pre class=command&gt;postgres@mirror:$/usr/local/pgsql/bin/initdb -E UNICODE --locale=C -D /usr/local/pgsql/data&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;เมื่อเราทำการทดสอบดูก็ได้ผลตามนี้&lt;br /&gt;&lt;pre class=box&gt;&lt;br /&gt;เทสต์แล้วครับ บนเครื่องที่ใช้ทำงานจริง work work work ดูการ select ซะก่อน&lt;br /&gt;postgres@mirror:~/tmp$ /usr/local/pgsql/bin/psql v3_repl_db&lt;br /&gt;Welcome to psql 8.0.3, the PostgreSQL interactive terminal.&lt;br /&gt;&lt;br /&gt;Type: \copyright for distribution terms&lt;br /&gt;\h for help with SQL commands&lt;br /&gt;\? for help with psql commands&lt;br /&gt;\g or terminate with semicolon to execute query&lt;br /&gt;\q to quit&lt;br /&gt;&lt;br /&gt;v3_repl_db=# select item_common_name from b_item where UPPER(item_common_name) like '%cpm%';&lt;br /&gt;item_common_name&lt;br /&gt;------------------&lt;br /&gt;(0 rows)&lt;br /&gt;&lt;br /&gt;v3_repl_db=# select item_common_name from b_item where LOWER(item_common_name) like '%cpm%';&lt;br /&gt;item_common_name&lt;br /&gt;---------------------------------&lt;br /&gt;CPM .-inj ( 10 mg./ml. ) *&lt;br /&gt;CPM .-tab ( 4 mg. )*&lt;br /&gt;CPM .-Syr (2mg./5ml.) - 60ml.&lt;br /&gt;CPM hand&lt;br /&gt;CPM Elbow&lt;br /&gt;CPM&lt;br /&gt;(6 rows)&lt;br /&gt;&lt;br /&gt;v3_repl_db=# &lt;/pre&gt;&lt;br /&gt;จริงๆ ผมก็พึ่งนึกได้ว่าตอนที่ลง postgres จากแพกเกจของเดเบียนน่ะ ก่อนที่เค้าจะ initdb น่ะเค้าก็ถามเหมือนกันว่าจะใช้ locale เป็น C หรือว่า en_US ไอ้เราความที่เคยตัวซะชินก็ Enter ผ่าน (Enter ผ่านแล้วมันไม่มี error เรื่องนี้) เอ้อก็ต้องขอโทษขอโพยด้วยที่ไปนึกเหมาเอาว่าเกิดจากเดเบียน แฮ่ แฮ่ กว่าจะค้นหาปัญหาได้ก็ผ่านไปเดือนกว่าๆ ถ้าเกิดอะไรขึ้นกะเซอร์เวอร์ที่ให้บริการจริง ป่านนี้คงเอาหน้าไปไว้ที่ไหนไม่ได้แล้วล่ะ คิดๆอยู่เหมือนกันว่าจะเอาปัญหาไปถามที่ LTN ไหนก็เล่าแล้ว เล่าให้ฟังเลยดีกว่าว่า ตอนที่ไปงาน &lt;a href=http://www.tmi.or.th/TMI2005/&gt; TMI 2005 &lt;/a&gt; ปีนี้คณะแพทยศาสตร์ มหาวิทยาลัยเชียงใหม่รับเป็นแม่งาน ก็ได้เจอกับ&lt;a href=http://linux.thai.net/plone/Members/ott/&gt; คุณ ott (ภัทระ  เกียรติเสวี) &lt;/a&gt; ด้วย ขออนุญาตพาดพิงถึงหน่อย ในฐานะที่ติดตามงานของแกมานานตั้งแต่ทำ &lt;a href=http://www.nectec.or.th/linux-sis/&gt; Linux-SIS &lt;/a&gt; แล้ว วันนั้นก็เข้าไปนั่งฟังคุณ ott คุยเรื่องเกี่ยวกับ Linux และการนำไปใช้งาน หลังจากจบ session แล้วผมก็ได้มีโอกาสได้พูดคุยแล้วก็เล่าให้ฟังถึงปัญหาที่ผมเจอเข้าจริง คุณ ott ก็อุตสาห์ถามย้ำแล้วนะ ว่าเซต locale แล้วหรือยัง ไอ้เราก็ยังไม่ค่อยเข้าใจ (บ้านน๊อก บ้านนอก) กลับมาก็พยายามมาค้นดู ก็เลยเจอคำตอบจังเบ้อเร่อ ก็คุยกันนานพอสมควร ทราบว่าตอนนี้กลับมาอยู่เมืองไทยแล้ว ทำธุรกิจเปิดบริษัท &lt;a href=http://www.mm.co.th&gt; metamedia &lt;/a&gt; ร่วมกับ &lt;a href=http://poonlap.blogspot.com&gt; คุณพูลลาภ &lt;/a&gt; ก็ขออำนวยอวยพรให้กิจการก้าวหน้าด้วยดีนะครับ วันหน้าผมอาจจะมีโอกาสไปเป็นลูกค้า้บ้างก็ได้ถ้าปีหน้า defend งบได้มากๆ สรุปแล้วก็ Happy ที่ได้ผ่านเหตุการณ์อันไม่คาดฝันแล้วพยายามแก้ปํญหาไปได้ถึงแม้ว่า จะช้าไปมาก ปัญหามา ปัญญาก็มี ความรู้ก็ได้มากขึ้น กำไรเห็นๆ&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;พูดถึง TMI 2005 นิดนึงว่าปีนี้ค่อนข้างเงียบเหงาไปหน่อย อาจจะเป็นเพราะว่า ขาใหญ่ คือ Intel ไม่ได้เป็น titanium sponsor กลายเป็น Sun Microsystem ไปซะ บูตก็เลยน้อย พริตตี้ก็เลยพลอยน้อยไปด้วย (สาเหตุใหญ่ที่ชอบไปงานคอม เหอ เหอ)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-113518693029828571?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/113518693029828571/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=113518693029828571' title='2 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113518693029828571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113518693029828571'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/12/blog-post_22.html' title='ต้นตอของปัญหา'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-113361823890063941</id><published>2005-12-03T20:53:00.000+07:00</published><updated>2005-12-03T20:57:18.913+07:00</updated><title type='text'>เยือนถิ่นชาละวัน</title><content type='html'>ผ่านเรื่องที่ซีเรียสมาแล้วก็มาเล่าเรื่องที่เบาๆ กันหน่อย เดือนก่อน (พ.ย.) ผมมีโอกาสเดินทางไปต่างจังหวัด (&lt;a href= http://th.wikipedia.org/wiki/%E0%B8%88%E0%B8%B1%E0%B8%87%E0%B8%AB%E0%B8%A7%E0%B8%B1%E0%B8%94%E0%B8%9E%E0%B8%B4%E0%B8%88%E0%B8%B4%E0%B8%95%E0%B8%A3&gt;พิจิตร&lt;/a&gt;) ซึ่งมีคำขวัญประจำจังหวัดว่า "ถิ่นประสูติพระเจ้าเสือ แข่งเรือยาวประเพณี พระเครื่องดีหลวงพ่อเงิน เพลิดเพลินบึงสีไฟ ศูนย์รวมใจหลวงพ่อเพชร รสเด็ดส้มท่าข่อย ข้าวเจ้าอร่อยลือเลื่อง ตำนานเมืองชาละวัน" ครั้งแรกเมื่อวันที่ 19 ก็ไปเยี่ยมญาติน่ะครับ เป็นน้องของแม่ยาย แกไม่สบายป่วยเป็นมะเร็งที่ทรวงอก ออกเดินทางกันเช้ามืดวันที่ 19 ประมาณตีห้าครึ่งมีผม แม่ของเด็ก แล้วก็เด็กๆ ไปแวะรับ แม่ยายกับพี่ของแม่ยายอีกรวมเป็น 6 คนผู้ใหญ่ 4 เด็ก 2 ครั้งแรกที่ก็ไปเริ่มต้นที่อำเภอเถิน แล้วก็เดินทางจากอำเภอเถินเข้าสู่อำเภอทุ่งเสลี่ยมจังหวัดสุโขทัย ตามทางหลวงหมายเลข 1048 เมื่อยังอยู่ในเขตอำเภอเถิน เป็นเส้นทางที่ค่อนข้างชำรุด แคบ เปลี่ยว และคดเคี้ยว ไม่เหมาะในการเดินทางในกลางคืน ต่อเมื่อเข้าสู่เขตอำเภอทุ่งเสลี่ยมแล้วค่อยดีขึ้น ก็มองเห็นสภาพชีวิตของชาวบ้านในฤดูเก็บเกี่ยว เริ่มเห็นรถอีแต๋นแล่นขนข้าว กันค่อนข้างหนาตา ถึงอำเภอสวรรคโลก ก็ใช้เส้นทางหมายเลข 101 ถึงอำเภอศรีสำโรงแวะกินข้าวเช้ากัน ช่วงตั้งแต่สวรรคโลกมาถึงศรีสำโรงก็เริ่มเห็นว่าการชลประทานที่นี่ดีมาก ปลูกข้าวนาปรังกันเขียวขจีเต็มทุ่งนาไปหมด จากศรีสำโรงไปสุโขทัยก็ใช้เวลาไม่นานมากนัก ผมเลือกใช้เส้นทางเลี่ยงเมือง เนื่องจากไม่อยากเข้าไปหลงทางในตัวเมืองสุโขทัย มุ่งสู่อำเภอกงไกรลาศด้วยทางหลวงหมายเลข 12 ยาวถึง &lt;a href=http://th.wikipedia.org/wiki/%E0%B8%88%E0%B8%B1%E0%B8%87%E0%B8%AB%E0%B8%A7%E0%B8%B1%E0%B8%94%E0%B8%9E%E0%B8%B4%E0%B8%A9%E0%B8%93%E0%B8%B8%E0%B9%82%E0%B8%A5%E0%B8%81&gt;จังหวัดพิษณุโลก&lt;/a&gt; ซึ่งบางช่วงก่อนที่เข้าตัวเมืองพิษณุโลกมีการปรับปรุง เพื่อขยายทำให้การเดินทางช้าลงไปพอสมควร ทีนี้ก็มุ่งหน้าไปจังหวัดพิจิตร ด้วยเส้นทางสายเลี่ยงเมืองอีกเช่นเคย โดยจุดหมายอยู่ที่ อำเภอวชิรบารมี จังหวัดพิจิตร ตามทางหลวงหมายเลข 117 ผ่านมหาวิทยาลัยนเรศวร ผ่านนิคมอุตสาหกรรมภาคเหนือตอนล่าง แล้วก็เลี้ยวซ้ายเปลี่ยนไปใช้ทางหลวงหมายเลข 115 เข้าสู่อำเภอสามง่าม อำเภอเมืองจังหวัดพิจิตร จากวชิรบารมีถึงพิจิตร เนี่ยเห็นว่าปลูกข้าวนาปรังกันเป็นล่ำเป็นสัน บางแห่งก็เริ่มเก็บเกี่ยวด้วยรถเกี่ยวข้าว บางแห่งก็เริ่มหว่านเมล็ดกล้า บางแห่งต้นกล้าก็เริ่มโต มองดูเขียว ก็ถึงบ้านคลองคู้  อ.เมือง สิ้นสุดการเดินทางเมื่อเวลา 11 นาฬิการวมใช้เวลา 5 ชั่วโมงกว่าๆ ก็ค้างคืนซะคืนหนึ่ง รุ่งเช้าก็พาเด็กๆ ไปเที่ยวดูปลาที่บึงสีไฟ ก่อนเดินทางกลับ ซึ่งกว่าเด็กๆ จะยอมกลับเนื่องจากเพลินกับการให้อาหารปลาที่บึงก็ปาเข้าไปเที่ยงวันพอดี ขากลับผมไม่ได้กลับทางเดิมเนื่องจากรู้สึกว่ามันขับลำบาก อีกอย่างนึงก็คืออยากจะลองเดินทางอีกเส้นทางหนึ่ง คือจาก พิจิตร ตามทางหลวงหมายเลข 115 ผ่านสามง่าม วชิรบารมี เข้าสู่ &lt;a href=http://th.wikipedia.org/wiki/%E0%B8%88%E0%B8%B1%E0%B8%87%E0%B8%AB%E0%B8%A7%E0%B8%B1%E0%B8%94%E0%B8%81%E0%B8%B3%E0%B9%81%E0%B8%9E%E0%B8%87%E0%B9%80%E0%B8%9E%E0%B8%8A%E0%B8%A3&gt;จังหวัดกำแพงเพชร&lt;/a&gt; ช่วงนี้เป็นทางตรงยาวสุดลูกหูลูกตา รถราก็พอประมาณ ไม่ชุมมากนักอาจจะเป็นเพราะช่วงเที่ยง ก็เป็นได้ ทิวทัศน์ข้างๆ ทางก็เป็นนาปรัง สลับกับไร่อ้อย ให้เห็นเป็นระยะ บังเอิญฟังวิทยุอยู่ ดีเจเหมือนจะรู้ใจ เปิดเพลง ไร่อ้อยคอยรักของ หนู มิเตอร์ ก็ทำให้นึกภาพได้ชัดเจนมากขึ้น จากถนนหมายเลข 115 ก็มาบรรจบกับถนนพหลโยธิน (หมายเลข 1) ก็ใช้เส้นทางนี้ต่อจนถึงอำเภอเถิน แล้วก็แยกเข้าอำเภอลี้ด้วยเส้นทางหมายเลข 106 (พหลโยธินเดิม) จนถึงบ้านเวลา 5 โมงเย็น รวมระยะทางทั้งขาไปและขากลับก็ 687 ก.ม. หลังจากนั้นไม่กี่วันประมาณวันศุกร์ที่ 26 ก็ทราบข่าวว่าน้าแกเสียแล้ว การเดินทางครั้งที่สองก็เริ่มขึ้นเมื่อวันอังคารที่ 29 เพื่อไปร่วมฌาปนกิจศพ Trick นี้ผมเลือกใช้เส้นทางสาย เถิน ตาก กำแพงเพชร พิจิตร แทนทั้งขาไปและกลับ รู้สึกว่าขับได้สะดวกกว่าและเส้นทางไม่ซับซ้อนมากนัก พื้นผิวการจราจรก็ดีทีเดียว แต่ไปคราวนี้ไม่ได้ไปค้าง ไปเช้าเย็นกลับ ซึ่งเริ่มที่ 8 โมงเช้าหลังจากที่ไปส่งเด็กๆ ที่โรงเรียนก่อน ตอนเย็นก็ฝากเด็กๆ ไว้กับ ปู่-ย่า ไปก่อน เพราะคิดว่าคงจะกลับถึงบ้านดึก ซึ่งก็กว่าจะทำพิธีก็ปาเข้าไปสามโมงเย็น แต่พิธีการค่อนข้างรวบรัดไม่เยิ่นเย้อเหมือนพิธีทางเหนือ ซึ่งเริ่มประมาณ บ่ายโมง แต่กว่าจะเสร็จก็ปาเข้าไปสามสี่โมงเย็น ทางภาคกลางไม่นิยมจูงศพ ไปที่ป่าช้าเหมือนภาคเหนือ เนื่องจากที่วัดมักจะมีเมรุอยู่ในวัดเลยทำให้ลดเวลาลงไปได้เยอะ แต่ถึงกระนั้นกว่าจะได้เวลาเดินทางกลับก็ไปเข้าไป 17.30 น. ขากลับก็ไม่สามารถใช้ความเร็วมากนักเนื่องจากไม่ได้เอารถเก๋งที่ใช้ทุกวันไป เนื่องจากคิดว่าน่าจะเอารถกระบะไปจะดีกว่า ญาติพี่น้องจะได้ไปด้วยกันหลายๆ คน (แฟนผมเนี่ยญาติเยอะ) ผมก็รับหน้าที่โชเฟอร์ไปคนเดียว กว่าจะถึงบ้านก็ปาเข้าไปตั้ง 5 ทุ่มกว่าๆ เกือบเที่ยงคืน เนื่องจากเหยียบไม่ไหว บรรทุกหนัก ขากลับนี่ได้ส้มท่าข่อยมาหลายสิบลูก แค้นที่ไปครั้งก่อนหาซื้อไม่ได้ 5555 รสชาดก็สมกับคำขวัญของจังหวัดเค้าล่ะครับ หวาน ชุ่มคอดี ถ้ามีโอกาสไปอีกจะไปเหมาสวนเลยล่ะ ตั้งใจไว้อย่างนั้น หรือว่าจะเอาลำไยไปแลกเอา อิ อิ ระยะทางไป-กลับก็ 666 กิโลเมตร พอดิบพอดี&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-113361823890063941?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/113361823890063941/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=113361823890063941' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113361823890063941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113361823890063941'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/12/blog-post.html' title='เยือนถิ่นชาละวัน'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-113361261370937579</id><published>2005-12-03T19:15:00.000+07:00</published><updated>2005-12-03T19:23:33.726+07:00</updated><title type='text'>Hospital OS V III  era has Begun.</title><content type='html'>เกือบเดือนที่ไม่ได้มาบล็อก เนื่องจากสาละวนอยู่กับการเตรียมการแก้ไขปัญหาที่พบจากบล็อกเมื่อเดือนก่อน ว่าจะยังยื้ออยู่กับ PostgreSQL 7.4.7 อยู่ หรือว่าจะใช้เวอร์ชั่นใหม่กว่าคือ 8.0.x ตามที่ทางทีมงานแนะนำซึ่งชาวบ้านชาวช่องที่ขึ้นระบบไปแล้วเค้าก็ใช้กัน ไอ้เราจะมาดันทุรังใช้ต่อหรือ คิดอยู่ คิดทบทวนตั้งนาน ก็ต้องยอมอัพ PostgreSQL ไปใช้ 8.0.x ให้เหมือนๆ กัน เวลาคุยกันกับทีมงานจะได้คุยกับเค้าได้ เป็นคำตอบสุดท้าย...&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;ตัดสินใจว่าจะใช้ PostgreSQL แบบคอมไพล์จากซอร์สดีกว่า เนื่องจากยังไม่อยากจะอัพดิสโทรไปเป็น Etch ประกอบกับทดสอบแล้วบนเครื่องที่ใช้ทำงาน ว่า Sarge+PostgreSQL 8.0.3 (Compile เอง) มันก็เวอร์คดีไม่มีปัญหา สิ่งที่ไม่ได้คิดว่าจะเป็นปัญหาแม้แต่น้อยก็คือว่า เมื่อจัดการ apt-get remove --purge postgresql บนเครื่องที่ใช้งานจริง + เครื่องที่ใช้ทำดาต้าเบสมิเรอร์ ตามขั้นตอนต่อไปนี้&lt;br /&gt;&lt;pre class=command&gt;&lt;br /&gt;db :~/tmp/postgresql-8.0.3/#./configure --prefix=/usr/local/pgsql&lt;br /&gt;db :~/tmp/postgresql-8.0.3/#make&lt;br /&gt;db :~/tmp/postgresql-8.0.3/#make install&lt;br /&gt;db :~/tmp/postgresql-8.0.3/#mkdir /usr/local/pgsql/data&lt;br /&gt;db :~/tmp/postgresql-8.0.3/#chown -R postgres.postgres /usr/local/pgsql/data&lt;br /&gt;db :~/tmp/postgresql-8.0.3/#chmod -R 700 /usr/local/pgsql/data&lt;br /&gt;db :~/tmp/postgresql-8.0.3/#su postgres&lt;br /&gt;db :~/tmp/postgresql-8.0.3/$/usr/local/pgsql/bin/initdb -E UNICODE -D /usr/local/pgsql/data&lt;br /&gt;db :~/tmp/postgresql-8.0.3/$exit&lt;br /&gt;db :~/tmp/postgresql-8.0.3/#nano -w contrib/start-scripts/linux&lt;br /&gt;db :~/tmp/postgresql-8.0.3/#cp contrib/start-scripts/linux /etc/init.d/postgresql-8.0&lt;br /&gt;db :~/tmp/postgresql-8.0.3/#chmod 700 /etc/init.d/postgresql-8.0&lt;br /&gt;db :~/tmp/postgresql-8.0.3/#/etc/init.d/postgresql-8.0 start&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ต่อไปก็เป็นการสร้างดาต้าเบส ดัมพ์ฐานข้อมูลเดิมกลับเข้าไป อัพเดทด้วย SQL สำหรับใช้กับเวอร์ชั่นสาม ทั้งสองเครื่องใช้เวลาไม่นานมากเท่าไรประมาณชั่วโมงกว่าๆ พร้อมกับทำดาต้าเบสมิเรอร์ด้วยแหละ อะไรจะขนาดนั้น จากที่เริ่มต้นปิดระบบตอนประมาณ 3 ทุ่มๆกว่าเสร็จก็ 4 ทุ่มกว่าๆ ของคืนวันที่ 30 พ.ย 2548 ก็เดินลงมาบอกน้องพยาบาลเวรให้เริ่ม login เข้าทำงานได้ อิ อิ พอเริ่มเปิด visit ผู้ป่วยบันทึกอาการเจ็บป่วยเสร็จ พอจะสั่งยาเท่านั้นแหละ ค้นหารายการออเดอร์ไม่เจอ ตอนนั้นยังไม่ซีเรียสอะไรมาก ลองโทรไปถามเบะซะหน่อย คำตอบที่ได้รับปรากฏว่า postgres ไม่สนับสนุนการใช้งานแบบ multibyte ทำให้ค้นหารายการออเดอร์ไม่เจอ เป็นเหตุการณ์เดียวกันกับที่ ชุมแสง และเป็น Critical มากเลยสำหรับซอพท์แวร์ที่เกี่ยวกับการให้บริการสุขภาพ ถ้าสั่งยาไม่ได้ก็แทบจะไม่มีความหมายอะไร ไม่ได้เป็นแค่เซอร์เวอร์ที่ใช้บริการจริงๆ นะ ตัวที่ทำเป็นมิเรอร์ก็เป็นไปกับเค้าด้วย โอ จอร์ช มันยอดมากเลย มีทางแก้มั๊ย อากาศตอนสี่ทุ่มกว่าๆ ที่ทุ่งหัวช้างก็เย็นมากแล้ว แต่ทำไมผมรู้สึกร้อนๆ เหงื่อเต็มฝ่ามือไปหมด ที่ชุมแสงแก้ปัญหาโดยเปลี่ยนจากเดเบียนไปเป็น Redhat Enterprice ที่เบะติดเอาไปด้วยแล้วคอมไพล์ postgres ใหม่ก็สามารถทำงานได้ปกติ เอ้อแล้วกรู จะไปเอา Redhat Enterprice มาจากไหนฟะ ดึกดื่นขนาดนี้แล้ว อย่าว่าแต่ดึกๆ เลย กลางวันแสกๆ ยังไม่มีปัญญาไปหา Distro อื่นหรอก ก็คบเดเบียนมานานโขแล้วจนไม่คิดที่จะใช้อย่างอื่น ก็มีแต่เดเบียน เอ๊ะแต่ทำไมทองแสนขันถึงใช้เดเบียน+postgresql คอมไพล์ได้ว่ะ เริ่มมีกำลังใจมานิดๆ แต่ตอนนี้มันห้าทุ่มกว่าๆ แล้วจะโทรไปถามก็ดึกมาก ไม่เป็นไรลองคอมไพล์ใหม่เพิ่ม option --enable-multibyte ไปด้วยซะ ก็ตอนแรกๆ ที่ใช้ Postgres ก็ใช้แบบคอมไพล์นี่แหละ แต่ตอนนั้น option เยอะกว่านี้มากจำไม่ได้แล้ว จำได้แค่ว่าใช้ Linux SIS + PostgreSQL 7.1.3 ก็ใช้มาตลอดตั้งแต่เดือน ตุลาคม 2545 (เริ่มใช้ Hospital OS เวอร์ชั่นแรกๆ) จนถึง มกราคม 2548 ก็เปลี่ยนมาใช้เดเบียนซึ่งยังไม่ stable+PostgreSQL ที่มากับ Distro พร้อมๆกับ upgrade มาเรื่อยจน Sarge กลายเป็น Stable และ PostgreSQL หยุดอยู่ที่ 7.4.7 กลับมาที่การคอมไพล์ครั้งที่สองบวก option --enable-multibyte ไปด้วยผลออกมาก็คือยังไม่สามารถใช้งานได้ มาถึงตอนนี้เริ่มเครียดเนื่องจากว่าเข้าสู่วันใหม่แล้ว โชคดีที่เวรดึกไม่มีผู้มารับบริการเลยทำให้ตัดความกังวลไปได้บ้าง คิดว่าจะต้องลงเดเบียนใหม่อีกที ทีนี้ขออัพเกรดไปเป็น Etch เพื่อเลือกใช้ PostgreSQL 8.0.3 ที่มากับ Distro อาจจะตัดปัญหาเรื่อง multibyte ไปได้ (คิดอะไรไม่ออกแล้วตอนนี้ต้องเสี่ยง) เสร็จประมาณตีสามกว่ารวมเวลาที่คอยการ fetch package จากอินเทอร์เน็ตด้วย เน็ตก็ไม่ค่อยเป็นใจเท่าไร โอยกว่าจะก้าวหน้าที่ละ k ใจจะขาดซะให้ได้ ผลที่ออกมาน่ะเรอะ เหอะ เหอะ เหมือนเดิม ตอนนี้เครียดกว่าเดิมอีก เหลือเวลาอีกไม่กี่ชั่วโมงก็จะสว่างแล้ว แล้วยังมีคลินิคเบาหวานด้วย โอ จอร์ช พระเจ้าจะช่วยกรู ได้ไหมฟะเนี่ย ทำงัยดีล่ะ เอางี้แล้วกันถอยกลับไปใช้เวอร์ชั่นสองอีกครั้ง เอาเครื่องที่เป็นมิเรอร์นั่นแหละ ให้บริการไปก่อน ลืมบอกไปว่าหลังจากที่พบว่ามีเออร์เรอร์เรื่อง multibyte ผมก็เอา PostgreSQL 8.0.3 ที่คอมไพล์บนเครื่องมิเรอร์ออก แล้วก็กลับไปใช้ 7.4.7 เหมือนเดิมปรากฏว่าไม่มีเออร์เรอร์เรื่อง multibyte แฮะ อย่างน้อยก็ยังอุ่นใจได้อย่างน้อยก็สักวันหนึ่ง แต่จะหวังให้ใช้งานหนักๆ เร๊อะ คงยากเนื่องจากสเปคของ Hardware เป็นสเปคของ Desktop PC ธรรมดาลำพังการเอามาทำเป็นมิเรอร์เนี่ยก็ค่อนข้างโหลดมากแล้ว มองดูนาฬิกาอีกทีตีสามกว่าเกือบตีสี่แล้ว เอาเป็นลงเดเบียนอีกทีน่ะ คราวนี้เอา Sarge เหมือนเดิมก็แล้วกันแล้วคอมไพล์ PostgreSQL เอา ลองดูอีกทีน่ะยังพอมีเวลา ทีนี้ตอนลงเพิ่ม Repository ของ update เข้าไปด้วยตีห้ากว่าๆ ก็เสร็จ ตอนที่ login เข้าไปเทสต์น่ะ ผมงี้ลุ้นใจจะขาด ในที่สุดสวรรค์ยังเมตตา ไม่ให้ผมต้องรับกรรมไปมากกว่านี้อีก กว่าจะเริ่ม fine tunning , set up crontab อีกสว่างคาตาเลยครับ คำพูดที่ว่าฟ้าเหลืองน่ะ มีจริงผมยืนยันได้ เจอกับตัวเองเข้าถึงรู้ เหอ เหอ&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;ปัญหาที่เกิดขึ้นผมพอจะเดาเอาเอง ซึ่งอาจจะไม่ใช่สาเหตุจริงๆ ก็ได้&lt;br /&gt;&lt;ol&gt;&lt;br /&gt; &lt;li&gt;Sarge ที่ติดตั้งบนเครื่อง Database Server ไม่ได้ update เลยอาจทำให้บางแพคเกจมีปัญหาในการใช้งาน PostgreSQL+mutibyte&lt;/li&gt;&lt;br /&gt; &lt;li&gt;เครื่องที่ทำเป็น Database Mirror ผมมักจะใช้เป็นเครื่องที่ทดลองการใช้งาน Debian อยู่เสมอและเปิดการอัพเดทด้วยทำให้ไม่มีปัญหากับ multibyte เมื่อใช้กับ Postgres 7.4.7 แม้ว่าจะคอมไพล์ 8.0.3 ไม่ผ่านแต่ก็สามารถ Down ลงมาใช้ของเดิมได้ &lt;/li&gt;&lt;br /&gt; &lt;li&gt;Etch ไม่มีระบบการ update security เนื่องจากยังอยู่ในการ Testing บางทีอาจจะยังไม่พบปัญหานี้ก็ได้ เป็นปัญหาของเดเบียนหรือว่า Postgres กันแน่ ?&lt;/li&gt; &lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;อย่างไรก็ดี เหตุการณ์เหล่านี้ก็ผ่านไปแล้วด้วยดี โรงพยาบาลก็สามารถให้บริการต่อได้ด้วย HospitalOS Version III ก็ต้องขอขอบใจน้องๆ ที่อยู่เวร คอยเป็นกำลังใจให้ ผมเองตอนเช้าเมื่อเห็นจุดบริการต่างๆ สามารถใช้งานด้วยความราบรื่นก็ดีใจ ที่เราในฐานะของฟันเฟืองชิ้นเล็กๆ ชิ้นหนึ่งในระบบ มีส่วนทำให้กลไกการทำงานสามารถก้าวหน้าต่อไปได้ ไม่ติดขัด แม้ว่าจะไม่มีใครรู้ ใครเห็น ก็ตามก็เป็นความสุขที่ได้ทำ นี่หรือคือชีวิตของผู้ดูแลระบบ ชีวิตที่อยู่เบื้องหลังความสำเร็จของการให้บริการ (ว่าเข้าไปนั่น)&lt;br&gt;&lt;br /&gt;ทีนี้ก็เหลือภาระงานอีกอย่างที่ต้องรีบเร่งทำ คือการทำมิเรอร์ ให้กับ Database จากประสบการณ์ที่ผ่านมาทำให้ไม่วางใจในเซอร์เวอร์เพี่ยงเครื่องเดียว คงต้องเหนื่อยอีกรอบ สู้โว๊ย&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-113361261370937579?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/113361261370937579/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=113361261370937579' title='1 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113361261370937579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113361261370937579'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/12/hospital-os-v-iii-era-has-begun.html' title='Hospital OS V III  era has Begun.'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-113112176778630092</id><published>2005-11-04T22:33:00.000+07:00</published><updated>2005-11-04T23:29:27.843+07:00</updated><title type='text'>อึดอัด</title><content type='html'>หลังจากที่ &lt;a href="http://www.hospital-os.com/"&gt;โครงการวิจัยและพัฒนาซอพท์แวร์สำหรับโรงพยาบาลขนาดเล็ก&lt;br /&gt;&lt;/a&gt; ได้ปล่อยตัวเวอร์ชั่นสามออกมาเรียบร้อยโรงเรียนภูเก็ตไปแล้วเมื่อเช้ามืดวันที่ 31 ตุลาคม ที่ผ่านมาและประกาศสัญญาอนุญาตให้ใช้ซอฟต์แวร์เป็นแบบ &lt;a href="http://developer.thai.net/gpl/"&gt;GPL&lt;/a&gt; ปรากฏว่าได้รับการตอบรับอย่างล้นหลาม รับดาวน์โหลดอย่างหูดับ ตับไหม้ เหอ เหอ ที่ใช้ &lt;a href="http://en.wikipedia.org/wiki/ADSL"&gt;ADSL&lt;/a&gt; ก็สบายกันไปแต่สำหรับผมต้องรออีกวันถึงจะดาวน์โหลดได้กะเค้า เห็นทีว่าอาจจะต้องเซพค่าโทรมือถือเอามาแชร์เป็นค่า ADSL บ้างคงจะดีไม่น้อย&lt;br /&gt;&lt;hr /&gt;แต่สิ่งที่ทำให้ผมรู้สึกอึดอัด คือ เจ้า SQL ที่ทำขึ้นมาเพื่ออัพเดทฐานข้อมูลจากเวอร์ชั่นสอง ไปเวอร์ชั่นสามนี่สิที่ทำให้หลายวันมานี้ต้องคร่ำเคร่งเพื่อค้นหาว่าทำไมฐานข้อมูลที่ใช้งานอยู่ทุกวันนี้จึงอัพเดทกะเค้าไม่ได้ซะที หลังจากที่ใช้เวลามามาก ประกอบกับสอบถามไปทางน้องๆ ทีมงานที่เขียนโปรแกรมกันอยู่ก็ทราบว่า ในเวอร์ชั่นสามนี้ น้องๆ ใช้ PostgreSQL 8.0.3 เป็นพื้นฐานกันอยู่ทำให้เวลาดัมพ์ข้อมูลออกมาจึงอยู่ในฟอร์แมตของเวอร์ชั่น 8 ซะเป็นส่วนใหญ่ และเมื่อเอามาใช้กับ PostgreSQL เวอร์ชั่น 7.4.7 (Sarge) ทำให้มีเอ๋อเหล๋อให้เห็นมากมายเหลือเกิน เช่น&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;คำสั่ง ALTER TABLE ADD COLUMN vn VARCHAR(255) DEFAULT ""; ก็ใช้ไม่ได้นะจ๊ะ ต้องใช้แบบนี้&lt;br /&gt;               บรรทัดแรก ALTER TABLE ADD COLUMN vn VARCHAR(255);&lt;br /&gt;               บรรทัดที่สอง ALTER TABLE ALTER COLUMN vn SET DEFAULT "";&lt;/li&gt;&lt;li&gt;คำสั่ง ALTER INDEX ก็ใช้ไม่ได้ต้องคอมเม้นท์ไว้จึงจะไม่มีเอ๋อเหล๋อ&lt;/li&gt;   &lt;li&gt;ที่น่าปวดหัวยิ่งกว่านั้นคือว่าตามข้อ 1 ข้างบนเนี่ยบางบรรทัดก็ทำตามได้ถูกต้องแต่บางบรรทัดก็ผ่านไปเฉยๆ เหมือนกับว่าถูกคอมเม้นท์ไว้ซะอย่างนั้น ทำให้ต้องมาคอยเช็คดาต้าเบสทุกตาราง ทุกคอลัมภ์ว่าครบหรือปล่าว สามร้อยกว่าตารางครับ&lt;br /&gt;  &lt;/li&gt;  &lt;/ol&gt;&lt;br /&gt;จนแน่ใจว่า SQL ที่เอามาโมดฟายใหม่นั้นทำครบทุกบรรทัดแล้วก็ลองมาเรียกจากตัว Application ดู ฮื่อๆ ทำให้เข่าอ่อนเลย ตัว Setup นั้นเรียกใช้ได้ไม่มีปัญหา แต่ตัว Class Main นั้นเรียกด้วย user ธรรมดาไม่ได้ เรียกได้เฉพาะ user admin แต่ก็ไม่ค่อยสมบูรณ์คือเจ้าตัว tab ต่างๆ ไม่ปรากฏให้เห็น ก็เลยลองโทรไปถามทั้ง henbe (Chief Programmer ในเวอร์ชั่นสาม) พร้อมกับส่ง Exception ไปให้ดู + schema ของฐานข้อมูลที่ได้ทำการอัพเดทไปแล้ว + SQL ที่โมดิฟาย เพื่อให้ตรวจสอบอีกทีนึงว่า ในดาต้าเบสนั้นน่ะ Table, Column ครบจริงๆ หรือปล่าว (ทำมาหลายวัน ตาอาจลายมองเห็นว่าครบก็ได้) เท่านั้นยังไม่พอยังแอบโทรไปถามโต้งอีกว่าเกิดจากอะไรได้มั่ง ก็ได้คำตอบที่ค่อนข้างทำให้เครียดเลยว่า ตัว jar file ทั้งหลายน่ะถูกเขียนขึ้นจากการทดสอบบน PostgreSQL 8.0.3 อาจจะมีผลได้นะเพ่&lt;hr&gt;&lt;br /&gt;ทางออกที่ดีที่สุดคือเปลี่ยนไปใช้ PostgreSQL 8.0.x ซะ ปัญหาทั้งหลายก็จะหายไป อันนี้เห็นด้วยว่ะ แต่หนักใจมากเนื่องจากที่ทำงานใช้ sarge ก็ postgres มันเป็น 7.4.7 ซึ่งก็ทำงานอย่างซ์่อสัตย์มาตลอด (ไม่มีความผิดอะไร ) จู่ๆ จะให้ทิ่งไปด้วยเหตุผลที่ว่า เธอร์ดีเกินไป (สำนวนเด็กแนวที่เห็นตาม MV ทั่วไป) ก็ทำไม่ได้ ถ้าทำก็คือ อัพทั้งดิสโทรขึ้นไปเป็น etch เลยเหยอ อันนี้ยิ่งไม่อยากทำในงานที่ต้องใช้ความเสถียรสูง เกิดดาต้าเบสหรือเครื่องเซอร์เวอร์เป็นอะไรไป กรูมิไปเกิดใหม่เลยเหรอฟะ หรือจะเอาซอร์สของ Postgresql 8.0.x มาคอมไพล์เองบน sarge ซึ่งก็เป็นทางออกที่มีเหลืออีกทาง ลง readline , zlib อีกสองแพกเกจก็คอมไพล์ได้แล้วว่ะ เออรู้สึกว่าง่ายหน่อย แต่ก็หนักใจเนื่องจาก dependency ของระบบผูกติดกันอย่างแน่นหนาเหลือเกิน บางโปรแกรมอาจเรียกไม่ได้ ยอมมั๊ย&lt;hr&gt;&lt;br /&gt;ทางออกในตอนนี้คือรอ ๆ รอมันไปเรื่อยๆ เหตุผลที่ต้องรอก็เพราะว่าเครื่องของหน่วยบริการปฐมภูมิ (Primary Care Unit PCU) ก็ยังไม่มาถึงซะที ทั้งๆ ที่น้องเค้าก็มาตามจิกอยู่ทุกวันว่าเมื่อไหร่จะได้ใช้โปรแกรมซะที (ไป Present ไว้ซะเยอะ แล้วเป็นงัยล่ะ) ตามเครื่องคอมให้หน่อยนะ หนูต้องบันทึกข้อมูลมากนะ อีกอย่างที่ต้องรอคือคำตอบจาก henbe ว่า schema ที่ส่งไปให้ดูน่ะครบหรือปล่าว ถ้าครบก็เป็นเรื่องของ henbe ที่ต้องไปตามดูบักต่อ แต่ถ้ามันไม่ครบก็ต้องตาแฉะหาวิธีอัพเดทให้ได้ คิดแล้วเหนื่อย ไอ้เช็ค SQL ไม่ค่อยยากใช้ editor ช่วยก็ได้แต่เช็คดาต้าเบสนี่ดิ มันเป็นอะไรที่ต้องใช้สมาธิสูงมาก แล้วต้องใช้กำลังใจมากด้วย (อิ อิ) เอ้าก็รอกันไป วัดกว่าจะสร้างเสร็จก็เป็นปี หมู่บ้านที่ผมอยู่ วิหารยังสร้างมาตั้งหลายปีแล้วยังไม่เสร็จซะที ช่วงนี้ตอนเย็นเลยหาเรื่องไปเตะชาวบ้านเค้าไปทั่ว เตะเค้าแล้วก็วิ่งหนีซะ (เล่นบอล) ค่อยหายอึดอัดหน่อย ก็ได้แต่หวังว่าคงไม่ต้องเปลี่ยนไปใช้ PostgreSQL 8.0.x นะ (ขอให้เป็นคำตอบสุดท้ายก็แล้วกัน)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-113112176778630092?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/113112176778630092/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=113112176778630092' title='5 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113112176778630092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113112176778630092'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/11/blog-post.html' title='อึดอัด'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-113056084933822225</id><published>2005-10-29T11:32:00.000+07:00</published><updated>2005-10-29T11:40:49.346+07:00</updated><title type='text'>apt-get update</title><content type='html'>กลับจากไปเที่ยวมา ก็ไม่ค่อยได้ใช้คอมพิวเตอร์เท่าไหร่ เนื่องจากแม่บ้านใช้ค้นคว้างานที่จะต้องไป Present ให้อาจารย์ที่ปรึกษาฟังเกี่ยวกับการค้นคว้าสิ่งที่ได้เรียนรู้มาตลอดระยะเวล าที่เรียนมา ปีกว่าๆ พึ่งจะมีโอกาสใช้เมื่อคืนนี้เอง ก็กะว่าจะ update ซะหน่อย ที่ไหนได้ พอสั่ง apt-get update ก็ได้ข้อความดังนี้&lt;br /&gt;&lt;pre class="file"&gt;&lt;br /&gt;debian:/home/uthai# apt-get update&lt;br /&gt;Get:1 http://linux.thai.net etch/main Packages [3477kB]&lt;br /&gt;Err http://linux.thai.net etch/main Packages&lt;br /&gt; Error reading from server - read (104 Connection reset by peer)&lt;br /&gt;Hit http://linux.thai.net etch/main Release&lt;br /&gt;Hit http://linux.thai.net etch/contrib Packages&lt;br /&gt;Hit http://linux.thai.net etch/contrib Release&lt;br /&gt;Hit http://linux.thai.net etch/non-free Packages&lt;br /&gt;Hit http://linux.thai.net etch/non-free Release&lt;br /&gt;Hit http://linux.thai.net ./ Packages&lt;br /&gt;Ign http://linux.thai.net ./ Release&lt;br /&gt;Get:2 http://linux.thai.net etch/main Sources [1334kB]&lt;br /&gt;Err http://linux.thai.net etch/main Sources&lt;br /&gt; Error reading from server Remote end closed connection&lt;br /&gt;Hit http://linux.thai.net etch/main Release&lt;br /&gt;Hit http://linux.thai.net etch/contrib Sources&lt;br /&gt;Hit http://linux.thai.net etch/contrib Release&lt;br /&gt;Hit http://linux.thai.net etch/non-free Sources&lt;br /&gt;Hit http://linux.thai.net etch/non-free Release&lt;br /&gt;Failed to fetch http://linux.thai.net/pub/mirrors/debian/dists/etch/main/binary- i386/Packages.gz  Error reading from server - read (104 Connection reset by peer )&lt;br /&gt;Failed to fetch http://linux.thai.net/pub/mirrors/debian/dists/etch/main/source/ Sources.gz  Error reading from server Remote end closed connection&lt;br /&gt;Reading Package Lists... Done&lt;br /&gt;W: Couldn't stat source package list http://linux.thai.net etch/main Packages (/ var/lib/apt/lists/linux.thai.net_pub_mirrors_debian_dists_etch_main_binary-i386_ Packages) - stat (2 No such file or directory)&lt;br /&gt;W: You may want to run apt-get update to correct these problems&lt;br /&gt;E: Some index files failed to download, they have been ignored, or old ones used  instead.&lt;br /&gt;debian:/home/uthai#&lt;br /&gt;&lt;/pre&gt;จ ริงแล้วผมเคยเจอเหตุการณ์เช่นนี้มาแล้ว แต่ก็ลองตื้อดู ครั้งสองครั้งก็โอเช แต่คราวนี้ไม่แฮะ ออกมารูปนี้ตลอด เลย apt-get อะไรต่อไปอีกไม่ได้ ใครเจอแบบนี้แก้ไขได้อย่างไร รบกวนเล่าให้ฟังเป็นวิทยาทานด้วยนะครับ จะว่าเน็ต้ช้าก็ใช่ แต่ไม่น่าจะช้าจนทำอะไรไม่ได้ขนาดนี้ ตอนที่บล็อกอยู่นี่สปีดก็ใช้ได้นะครับ เดี๋ยวจะลองค้นดูหน่อย มันอึดอัดซะเหลือเกิน โฮ่ย&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-113056084933822225?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/113056084933822225/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=113056084933822225' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113056084933822225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113056084933822225'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/10/apt-get-update.html' title='apt-get update'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-113055787872565043</id><published>2005-10-29T09:49:00.000+07:00</published><updated>2005-10-29T10:54:17.860+07:00</updated><title type='text'>1587 กิโลเมตร</title><content type='html'>ไม่ได้มาบล็อกซะนาน กลางเดือนที่ผ่านมาไปเที่ยวที่พัทยา จริงๆแล้วก็ไม่เชิงว่าไปเที่ยว น่าจะไปเป็นเพื่อนแม่บ้านกับเด็กๆ ซะมากกว่า แม่บ้านเค้าลงทะเบียนประชุมวิชาการประจำปี ที่สมาคมศิษย์เก่ารังสีเทคนิค โรงพยาบาลจุฬาลงกรณ์ สภากาชาดไทยจัด ที่พัทยา โรงเรียนเด็กๆ ก็ยังไม่เปิด ก็ถือเป็นโอกาสดีที่จะได้พาเด็กไปเที่ยวพักผ่อนกัน หลังจากที่ผัดผ่อนมานานแล้ว ก็ไปกันทั้งบ้าน พ่อ แม่ ลูกๆ ออกเดินทางตั้งแต่เช้าวันที่ 18 เวลาประมาณ ตีสี่ครึ่ง (ช้ากว่ากำหนดการไปสองชั่วโมง เนื่องจากนอนเพลินไปหน่อย) ก็เริ่มเดินทางจากลี้ ไปตามถนนพหลโยธินสายเก่า เหอะ เหอะ ผ่านเส้นทางที่ระยะทางไม่มาก แต่ใช้เวลาประมาณ หนึ่งชั่วโมง เนื่องจากความคดเคึ้ยวของเส้นทางที่ลัดเลาะไปตามภูเขา โค้งซ้าย โค้งขวา จนจำไม่ได้ว่ามากเท่าไหร่ ถึงอำเภอเถินก็เกือบสว่าง ใช้เวลาอีกประมาณชั่วโมงครึ่งก็ถึงจังหวัดตาก แล้วก็แวะทานข้าวเช้าแถวๆ ก่อนถึงกำแพงเพชร ก็ขับรถไปเรื่อยๆ ผ่านนครสวรรค์ ตอนนี้อากาศเริ่มร้อนแล้วก็ต้องขับด้วยความเร็วที่ต้องฝืนใจเหยียบ (ความจริงผมเลิกขับรถเร็วมานานแล้ว ตั้งแต่มีลูกคนแรก) ต้องวิ่งขวาตลอดเนื่องจากช่องทางด้านซ้าย ขรุขระ มีหลุม บ่อ แถมยังมีคลื่น อีกเป็นช่วงๆ ทำให้ต้องคอยระวังรถที่มาจากด้านหลัง รู้สึกว่าเริ่มเครียดกับการเดินทางมากขึ้น ช่วงตั้งแต่นครสวรรค์ จนถึงชัยนาท มองเห็นว่าข้างทางมีหนูนา ปิ้งขายเป็นระยะๆ แปลกใจมากว่าไปหาหนูนาจากไหนมาขายกันเหรอ ทุ่งนาก็เขียวอยู่ มันเป็นไปไม่ได้ที่ในขณะที่ทุ่งนายังไม่ได้เก็บเกี่ยวเนี่ยมักจะไม่ค่อยมีหน ูนานะ ที่บ้านผมกว่าจะมีหนูนาให้กินเนี่ย มันก็ต้องเกี่ยวข้าวเสร็จ ประมาณเดือนหรือสองเดือนนู่น เออ สงสัยว่าจะอิมพอร์ตมาจากที่อื่นๆ ที่น่าสนใจคือมีงูเห่าขายกันด้วย ขายกันเป็นๆ ตัวก็ไม่ได้ใหญ่โตอะไรมากมาย ผมก็ได้แต่ดูอยู่ห่างๆ เนื่องจากอากาศเริ่มร้อนมาก แล้วต้องรีบเดินทางด้วย ก็แวะพักเติมน้ำมันที่อยุธยา ก่อนที่จะเดินทางต่อในเส้นทางหมายเลข 9 (มอเตอร์เวย์) ก็ไปเรื่อยๆ จนแยกเข้าหมายเลข 7 (ถนนหมายเลข 34 เดิม) ก่อนที่จะแยกเข้าพัทยาที่แหลมฉบัง ไปตามถนนหมายเลข 3 (สุขุมวิท) จนถึงที่พัก(โรงแรม Wellcome Plaza) พัทยาใต้ ประมาณ 3 โมงครึ่ง เอ้อเดินทางกัน 11 ชั่วโมงครึ่งเชียวเร๊อะ ทำงัยได้ล่ะครับ รถก็เก่าพอสมควร ตอนวิ่งอยู่บนมอเตอร์เวย์ ผมสงสัยอยู่เหมือนกันว่าทำไมคนขับรถที่ขับแซงผมไปถึงเหลียวมองผมทุกที มานึกๆดูก็คงจะรำคาญที่ขับเร็วไม่พอ&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;ส องสามวันที่อยู่พัทยาก็ไม่มีกิจกรรมอะไรทำมากไปกว่า พาเด็กไปเล่นน้ำทั้งน้ำจืดและน้ำทะเล (เล่่นมันทั้งวัน เด็กภูเขาก็เงี๊ยะ เห็นทะเลทีก็ตื่นเต้น ) ผมพึ่งมารู้ทีหลังว่าเค้าแอบเอาขวดไปด้วยเพื่อที่จะเอาน้ำทะเลใส่ไปฝาก อา น้า ป้า ทั้งหลายที่อำแกไว้ก่อนจะมา 55555 ช่วงนี้ที่พัทยายังเป็นโลว์ซีซันอยู่เนื่องจากมีฝนตกอยู่บ้าง และน้ำทะเลยัง่ดำมากอยู่ (หรือมันก็เป็นอย่างงี๊) ที่น่าขำก็คือว่ามีอยู่วันนึงพาเด็กๆ ไปเที่ยวที่สถาบันวิทยาศาสตร์ทางทะเลที่บางแสน (อยู่ข้างๆ ม.บูรพา) ก็คิดถึงเหน่ง ขึ้นมา แต่ก็ไม่ได้โทรไปคุยด้วย พออีกวันก็โทรไปคุยด้วยปรากฏว่า เหน่งมาทำงานที่โรงพยาบาล ม.บูรพาพอดี เออ หัวเราะกันใหญ่ ไอ้เราก็เอ๋อ วันนั้นถ้าโทรหาก็เจอกันแล้ว ที่พัทยานี่ระบบการจราจรเค้าค่อนข้างตามใจคนขับมากเป็นพิเศษ (ขับกันมั่วมั่กมาก) ปาดซ้ายปาดขวากันให้มันส์ไปหมด คงจะเป็นเพราะว่ามีนักท่องเที่ยวชาวต่างชาติที่นิยมเช่ารถ ขับเที่ยวกันมาก ทางตำรวจก็คงจะหยวนๆ เพราะทางกวดขันกันจริงๆ ก็คงจะจับ ปรับกันไม่ไหว อาจจะทำให้เสียบรรยากาศการท่องเที่ยวไปด้วย คนไทยก็เลยขับตามใจตัวเองกันใหญ่ น้องสาวผมที่ทำงานที่ ICU (intensive care unit) โรงพยาบาลกรุงเทพ-พัทยา ก็เล่าให้ฟังว่ามีคนไข้ที่ถูกยิงเนื่องจากการขับรถปาดกันมารักษาที่โรงพยาบาลบ่อยๆ ทำให้ผมรู้สึกเสียวสันหลังขึ้นมาทันที&lt;br /&gt;&lt;hr /&gt;ว ันที่ 21 ก็เดินทางกลับกันกว่าจะเช็คเอ้าท์ได้ก็เกือบเที่ยง ออกจากที่พักกันจริงๆ ก็เที่ยงครึ่งแล้ว แวะที่หนองมนเพื่อซื้อของฝากอีกครั้งหลังจากวันก่อนไปซื้อที่ตลาดนาเกลือ แล้วได้ของไม่ครบ รถเยอะมากลืมนึกไปว่ามีวันหยุดชดเชยในวันจันทร์ที่ 24 อีกวันหนึ่งมิน่าการจราจรค่อนข้างคับคั่งเป็นพิเศษ ตั้งแต่สุขุมวิท มาถึงสายเอเชีย ก็ยังแน่นอยู่ มาค่อยยังชั่วหน่อยก็ตั้งแต่นครสวรรค์ขึ้นมา ช่วงขากลับรู้สึกเพลีย ก็เลยให้แม่บ้านออกแรงนิดนึงตั้งแต่สิงห์บุรี จนถึงนครสวรรค์ แวะทานข้าวเย็นกัน ตอนหกโมงกว่าๆ ทีนี้ความที่คิดถึงบ้านอย่างแรงก็เลยเหยียบคันเร่งเป็นพิเศษ แต่ก็ยังใช้ช่องทางขวาเหมือนเดิม เฮ้อ กลับถึงบ้านก็ 5 ทุ่มครึ่ง โดยสวัสดิภาพ รวมระยะทางก็ 1587 กิโลเมตร นับว่าโหดสำหรับรถยนต์นั่งขนาด 1500 ซีซี และคนขับที่ไม่ค่อยได้ขับทางไกลๆ อย่างผม&lt;br /&gt;&lt;hr /&gt;นึกๆ อยู่ว่าครั้งหน้าจะไปเที่ยวที่ไหนกันอีก เริ่มชอบกับการขับรถไปกันหลายๆคน พร้อมหน้าพร้อมตากันเยอะๆ เด็กก็อึดกันมาก ไม่หลับกันเลยคุยกันบ้าง เล่นกันบ้าง ทะเลาะกันบ้าง อยู่ที่เบาะหลัง รู้สึกว่าได้เติมพลังให้กับชีวิตอีกมากทีเดียว สดชื่นขึ้นถึงแม้ว่าจะล้าจากการเดินทาง แต่ก็พร้อมที่จะกลับไปลุยงานที่โรงพยาบาลต่อ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-113055787872565043?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/113055787872565043/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=113055787872565043' title='1 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113055787872565043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/113055787872565043'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/10/1587.html' title='1587 กิโลเมตร'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112930427271786982</id><published>2005-10-14T22:32:00.000+07:00</published><updated>2005-10-14T22:39:41.780+07:00</updated><title type='text'>SQL ตอนที่ 5</title><content type='html'>วันสองวันที่ผ่านมา คุณ SP (น่าจะมี &amp; คั่นกลางนะ) ถ้าจำไม่ผิดก็อยู่ที่ กระบุรี ระนอง ถามผ่านเวบบอร์ดมาว่า ทำอย่างไรถึงจะใช้ SQL หารายงาน 505 โดยแยกเป็นกลุ่มอายุต่างๆ ได้อย่างไร ฮื่อไอ้เราก็ดันตอบไปว่าไม่ยาก (ความคิดตอนนั้นคิดว่าไม่ยาก) แต่เมื่อผ่านมาได้ประมาณ 2-3 ชั่วโมงก็รู้ว่ามันหินนะ คือต้องเล่นกับวันที่ ที่เป็น varchar อีกแล้วล่ะ แต่ก็ไม่เป็นไร เราก็ลองมาทำดู ก็พอเห็นแนวอยู่บ้าง  ไหนๆก็ลองทำแล้วบันทึกไว้ซะหน่อย เตือนความจำไว้ก็ไม่เสียหายอะไร เลยมีเรื่องมาเล่าสู่กันอีกแล้ว หลังจากหมดมุขไปนาน ฮ่าๆๆๆๆ&lt;br&gt;&lt;br /&gt;โจทย์มีอย่างนี้ครับ ช่วงอายุที่คุณ SP ต้องการแบบนี้&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;คนไข้กลุ่ม 505 ช่วงอายุ&lt;br /&gt;0-4&lt;br /&gt;5-9&lt;br /&gt;10-14&lt;br /&gt;15-19&lt;br /&gt;20-24&lt;br /&gt;25-29&lt;br /&gt;30-34&lt;br /&gt;35-39&lt;br /&gt;40-44&lt;br /&gt;45-49&lt;br /&gt;50-54&lt;br /&gt;55-59&lt;br /&gt;60-64&lt;br /&gt;55-69&lt;br /&gt;70-74&lt;br /&gt;75-79&lt;br /&gt;80-84&lt;br /&gt;85+ &lt;/pre&gt;&lt;br /&gt;สร้างตารางเก็บช่วงอายุขึ้นมาอีกตารางดีไหม จะได้ไม่ต้องมากำหนดใน SQL ให้มันยุ่งยาก เวลาแก้ไขกลุ่มอายุ ก็มาแก้ไขที่ตารางเลยทีเดียว ลองสร้างกันดู เอาสักสามฟิลด์คือ&lt;br /&gt;&lt;ol&gt;&lt;br /&gt; &lt;li&gt;กลุ่มอายุ&lt;/li&gt;&lt;br /&gt; &lt;li&gt;อายุเริ่มต้น&lt;/li&gt;&lt;br /&gt; &lt;li&gt;อายุสิ้นสุด&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;แต่ผมว่าเพิ่มเลขกำกับกลุ่มไว้เป็นฟิลด์แรกเหอะ เวลาจัดเรียงจะทำให้มันง่ายอีก SQL สำหรับสร้างตารางก็น่าจะประมาณนี้ ตั้งชื่อตารางว่า r_age_group&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;CREATE TABLE r_age_group&lt;br /&gt;(&lt;br /&gt;  age_code int4,&lt;br /&gt;  age_description varchar,&lt;br /&gt;  age_begin varchar,&lt;br /&gt;  age_end varchar&lt;br /&gt;)&lt;/pre&gt;&lt;br /&gt;ทีนี้เราก็มา INSERT ข้อมูลเข้าตารางกันสองฟิลด์แรกคงไม่ยากเท่าไร แต่สองฟิลด์หลังนี่ ฉุกใจนึกขึ้นได้ว่าจะเอาอายุ เป็นปี หรือเป็นอะไรดีอ่ะ เอาเป็นปีรู้สึกว่ามันจะหยาบไปหน่อย พอดีไปคุยกันกับน้องที่อยู่งานส่งเสริม เค้าก็แนะนำมาว่าทำไม ไม่คิดเป็นเดือนล่ะ จะได้ละเอียดขึ้น เพราะเวลาเค้าทำงานสร้างเสริมภูมิคุ้มกันเด็ก เค้าก็นับอายุกันเป็นเดือน ไม่มีใครนับเป็นปีกันหรอก ว่างั้น อือ ได้ได้ เรคคอร์ดแรกก็น่าจะเป็นแบบนี้&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;INSERT INTO r_age_group VALUES (1,'อายุ 0-4 ปี','0','48');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;เหอะ เหอะ พอเรคคอร์ดที่สองสังเกตได้ว่า ทำไมต้องเป็น 5-9 ปี ด้วยอ่ะ แทนที่จะเป็น 4-9 ก็เรคคอร์ดแรกมันจบที่อายุ 48 เดือน มันก็ควรจะเริ่มต้นที่ 49 ซึ่งก็น่าจะอายุ 4 ปีอยู่ ก็กลับไปถามอีก เค้า (คนเดิม) ก็บอกมาว่า ที่คุณ SP ให้มาน่ะถูกแล้ว มากกว่า 48 เดือน ก็นับเป็น 5 ปีแล้ว เออ พึ่งรู้นะเนี่ย ขอคอนเฟิอร์มด้วยนะครับ จะได้กลับไปเฉ่งน้องคนนี้ ถ้าเกิดว่าข้อมูลที่ให้มาน่ะไม่ถูกต้อง เอาวะ ว่าแล้วก็นั่ง INSERT เข้าไปอีกประมาณนี้&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;INSERT INTO r_age_group VALUES (2, 'อายุ 5 ถึง 9 ปี', '49', '108');&lt;br /&gt;INSERT INTO r_age_group VALUES (3, 'อายุ 10 ถึง 14 ปี', '109', '168');&lt;br /&gt;INSERT INTO r_age_group VALUES (4, 'อายุ 15 ถึง 19 ปี', '169', '228');&lt;br /&gt;INSERT INTO r_age_group VALUES (5, 'อายุ 20 ถึง 24 ปี', '229', '288');&lt;br /&gt;INSERT INTO r_age_group VALUES (6, 'อายุ 25 ถึง 29 ปี', '289', '348');&lt;br /&gt;INSERT INTO r_age_group VALUES (7, 'อายุ 30 ถึง 34 ปี', '349', '408');&lt;br /&gt;INSERT INTO r_age_group VALUES (8, 'อายุ 35 ถึง 39 ปี', '409', '468');&lt;br /&gt;INSERT INTO r_age_group VALUES (9, 'อายุ 40 ถึง 44 ปี', '469', '528');&lt;br /&gt;INSERT INTO r_age_group VALUES (10, 'อายุ 45 ถึง 49 ปี', '529', '588');&lt;br /&gt;INSERT INTO r_age_group VALUES (11, 'อายุ 50 ถึง 54 ปี', '589', '648');&lt;br /&gt;INSERT INTO r_age_group VALUES (12, 'อายุ 55 ถึง 59 ปี', '649', '708');&lt;br /&gt;INSERT INTO r_age_group VALUES (13, 'อายุ 60 ถึง 64 ปี', '709', '768');&lt;br /&gt;INSERT INTO r_age_group VALUES (14, 'อายุ 65 ถึง 69 ปี', '769', '828');&lt;br /&gt;INSERT INTO r_age_group VALUES (15, 'อายุ 70 ถึง 74 ปี', '829', '888');&lt;br /&gt;INSERT INTO r_age_group VALUES (16, 'อายุ 75 ถึง 79 ปี', '889', '948');&lt;br /&gt;INSERT INTO r_age_group VALUES (17, 'อายุ 80 ถึง 84 ปี', '949', '1008');&lt;br /&gt;INSERT INTO r_age_group VALUES (18, 'อายุตั้งแต่ 85 ปีขึ้นไป', '1009', '10000');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;เผื่ออายุให้ตั้งหมื่นเดือนนะ สำหรับเรคคอร์ดสุดท้าย อิ อิ&lt;br&gt;&lt;br /&gt;แล้วก็ยังมีอีกตารางนึงนะ ที่ต้องสร้างคือตารางที่เก็บกลุ่มของโรคสำหรับรายงาน 505 ผมทำไว้ให้แล้วลองไปตรวจสอบความถูกต้องอีกทีแล้วกัน นะ ทั้งสองตารางมีให้ดาวน์โหลดข้างล่าง ไม่ต้องทำตามหรอก ทำไว้ให้แล้ว ตั้งใจอ่านให้เข้าใจคอนเซ็ปต์ก็พอแว๊ว ทีนี้ก็มาเริ่มสร้าง SQL กันเลย คิดมาได้ขนาดนี้&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; r_age_group.age_description AS description&lt;br /&gt; ,COUNT(t_visit.t_visit_id) AS total&lt;br /&gt;FROM&lt;br /&gt; t_visit&lt;br /&gt; ,t_patient&lt;br /&gt; ,t_diag_icd10&lt;br /&gt; ,disease_505_code&lt;br /&gt; ,r_age_group&lt;br /&gt;WHERE&lt;br /&gt; t_visit.t_patient_id=t_patient.t_patient_id&lt;br /&gt; AND t_visit.t_visit_id=t_diag_icd10.diag_icd10_vn&lt;br /&gt; AND t_visit.f_visit_type_id='1'&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;AND (t_diag_icd10.diag_icd10_number BETWEEN (disease_505_code.begin_code) and (disease_505_code.end_code))&lt;/span&gt;&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time,0,11) BETWEEN '2548-08-01' and '2548-08-05')&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;AND ((to_date(substr(t_visit.visit_financial_discharge_time,0,11),'yyyy-mm-dd') - &lt;br&gt;to_date(substr(t_patient.patient_birthday,0,11),'yyyy-mm-dd'))/30 BETWEEN (r_age_group.age_begin) and (r_age_group.age_end))&lt;/span&gt;&lt;br /&gt;GROUP BY&lt;br /&gt; r_age_group.age_description&lt;br /&gt; ,r_age_group.age_code&lt;br /&gt;ORDER BY&lt;br /&gt; r_age_group.age_code&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;มีอยู่สองบรรทัดที่อยากอธิบายเพิ่มเติม บรรทัดแรกคือ&lt;br /&gt;&lt;ol&gt;&lt;br /&gt; &lt;li&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;AND (t_diag_icd10.diag_icd10_number BETWEEN (disease_505_code.begin_code) and (disease_505_code.end_code))&lt;/span&gt;&lt;br /&gt; หมายความว่า ให้เลือกเอา รหัส icd10 ที่อยู่ระหว่างค่าเริ่มต้น กับค่าสิ้นสุด ของแต่ละกลุ่มในตาราง disease_505_code เท่านั้นนะ นอกเหนือจากนี้ไม่ต้องทำการเลือกมา&lt;/li&gt;&lt;br /&gt; &lt;li&gt;แล้วบรรทัดต่อมาที่สำคัญคือ &lt;span style="color: rgb(255, 0, 0);"&gt;AND ((to_date(substr(t_visit.visit_financial_discharge_time,0,11),'yyyy-mm-dd') - &lt;br&gt;to_date(substr(t_patient.patient_birthday,0,11),'yyyy-mm-dd'))/30 BETWEEN (r_age_group.age_begin) and (r_age_group.age_end))&lt;/span&gt;&lt;br /&gt; ขอแยกให้ดูชัดๆ t_visit.visit_financial_discharge_time คือเวลาที่จำหน่ายทางการเงิน มีค่าของฟิลด์เป็น varchar ในฟอรแมต แบบนี้ 2548-08-01,15:30:10 เราก็ตัดมาเฉพาะ ปี เดือน วัน โดยใช้ฟังก์ชัน SUBSTRING(t_visit.visit_financial_discharge_time,จากตำแหน่งที่ศูนย์,ความยาวของสตริงที่ต้องการตัด) ---&gt;substr(t_patient.patient_birthday,0,11) ก็ได้สตริงแบบนี้ --&gt; 2548-08-01 ทีนี้เราก็มาทำให้เป็นวันที่ซะ โดยการใช้ฟังก์ชั่นมาตรฐานของ PostgreSQL คือ to_date(สตริง,'yyyy-mm-dd') ก็จะได้วันที่ที่จบการรับบริการเป็นตัวตั้ง เช่นเดียวกันกับวันเกิดของผู้ใช้บริการคือ t_patient.patient_birthday ก็ทำเหมือนกัน ทีนี้ก็เอาวันที่มารับบริการตั้ง ลบด้วย วันเกิดของผู้ใช้บริการ ก็ได้ผลต่างคืออายุ แล้ว &lt;br&gt;&lt;br /&gt; แต่ผลต่างที่ได้เนี่ยยังเป็นวันอยู่ ถ้าหากว่าจะทำเป็นเดือน เราก็ต้องเอา 30 หรือ 31 ไปหารอีกต่อนึง ใช่ป่าว แต่ที่เห็นๆ มาเค้าใช้ 30 หารกัน ไม่ค่อยมีใครใช้ 31 อ่ะ ก็แปลกไปอย่าง ใครพอจะอธิบายเรื่องนี้ได้บ้างครับ ก็จะได้อายุออกมาเป็นเดือนตามที่เราต้องการ แล้วก็เอาอายุนี้ไปจัดกลุ่มตาม ค่า age_begin กับ age_end ในตาราง r_age_group นั้นแลลลลลล&lt;br /&gt; &lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;ก็ลองเอา SQL ไปรันก็ได้ผลลัพท์ออกมาแบบนี้&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;description     total&lt;br /&gt;อายุ 0 ถึง 4 ปี     27&lt;br /&gt;อายุ 10 ถึง 14 ปี     2&lt;br /&gt;อายุ 15 ถึง 19 ปี     1&lt;br /&gt;อายุ 20 ถึง 24 ปี     3&lt;br /&gt;อายุ 25 ถึง 29 ปี     8&lt;br /&gt;อายุ 30 ถึง 34 ปี     2&lt;br /&gt;อายุ 35 ถึง 39 ปี     2&lt;br /&gt;อายุ 40 ถึง 44 ปี     2&lt;br /&gt;อายุ 45 ถึง 49 ปี     3&lt;br /&gt;อายุ 50 ถึง 54 ปี     1&lt;br /&gt;อายุ 55 ถึง 59 ปี     3&lt;br /&gt;อายุ 60 ถึง 64 ปี     3&lt;br /&gt;อายุ 65 ถึง 69 ปี     5&lt;br /&gt;อายุ 70 ถึง 74 ปี     1&lt;br /&gt;อายุ 75 ถึง 79 ปี     3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;หากว่ายังไม่สะใจ อยากจะแยกเพศ ก็เพิ่มอีกสองบรรทัดนี้เข้าไประหว่าง&lt;br&gt;&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; r_age_group.age_description AS description&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;,SUM(CASE WHEN t_patient.f_sex_id='1' THEN 1 ELSE 0 END) AS male&lt;br /&gt; ,SUM(CASE WHEN t_patient.f_sex_id='2' THEN 1 ELSE 0 END) AS female&lt;/span&gt;&lt;br /&gt; ,COUNT(t_visit.t_visit_id) AS total&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;แล้วลองรัน SQL ที่เราแยกเพศดู&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;description          male          female          total&lt;br /&gt;อายุ 0 ถึง 4 ปี          7          20          27&lt;br /&gt;อายุ 10 ถึง 14 ปี          0          2          2&lt;br /&gt;อายุ 15 ถึง 19 ปี          1          0          1&lt;br /&gt;อายุ 20 ถึง 24 ปี          1          2          3&lt;br /&gt;อายุ 25 ถึง 29 ปี          0          8          8&lt;br /&gt;อายุ 30 ถึง 34 ปี          2          0          2&lt;br /&gt;อายุ 35 ถึง 39 ปี          0          2          2&lt;br /&gt;อายุ 40 ถึง 44 ปี          1          1          2&lt;br /&gt;อายุ 45 ถึง 49 ปี          3          0          3&lt;br /&gt;อายุ 50 ถึง 54 ปี          1          0          1&lt;br /&gt;อายุ 55 ถึง 59 ปี          2          1          3&lt;br /&gt;อายุ 60 ถึง 64 ปี          3          0          3&lt;br /&gt;อายุ 65 ถึง 69 ปี          1          4          5&lt;br /&gt;อายุ 70 ถึง 74 ปี          0          1          1&lt;br /&gt;อายุ 75 ถึง 79 ปี          3          0          3&lt;/pre&gt;&lt;br /&gt;แต่ผลลัพท์ที่ได้นี้ ยังไม่ค่อยสวยงามนักเนื่องจากว่าบางช่วงอายุ ที่ไม่มีผู้ใช้บริการก็ไม่แสดงออกมา คงแสดงออกมาเพียงกลุ่มอายุที่มีผู้ใช้บริการเท่านั้น ถ้าหากว่าอยากจะให้แสดงออกมาหมด ก็ต้องใช้น้องจอย (JOIN) ช่วย ลองกลับไปอ่าน เรื่องเดิมๆ แล้วจะเห็นว่า วิธีการ JOIN ทำอย่างไร&lt;br&gt;&lt;br /&gt;เกือบลืมไป ว่าไม่ได้เอาไฟล์ให้ดาวน์โหลดกันเยย&lt;br /&gt;&lt;ol&gt;&lt;br /&gt; &lt;li&gt;&lt;a href=http://www.hospital-os.com/~uthai/debian-install/sql/r_age_group.sql&gt;SQL สำหรับสร้างตาราง r_age_group&lt;/a&gt;&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;a href=http://www.hospital-os.com/~uthai/debian-install/sql/disease_505_code.sql&gt;SQL สำหรับสร้างตาราง disease_505_code&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br&gt;&lt;br&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;แหล่งความรู้และอ้างอิง&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;John C. Worsley and Joshua D. Drake, Practical PostgreSQL&lt;br&gt;&lt;br /&gt; O'Reilly &amp; Associates, Inc., CA ,USA &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112930427271786982?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112930427271786982/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112930427271786982' title='2 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112930427271786982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112930427271786982'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/10/sql-5.html' title='SQL ตอนที่ 5'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112887948141429695</id><published>2005-10-10T00:35:00.000+07:00</published><updated>2005-10-10T00:38:01.423+07:00</updated><title type='text'>เวบรีพอร์ต Update 9 ตุลาคม 2548</title><content type='html'>สัปดาห์ที่ผ่านมา พยายามปรับปรุงเวบรีพอร์ตอันเดิมๆ ให้มีประสิทธิภาพขึ้นกว่าเดิม เริ่มต้นด้วยรายงานผู้ป่วยเบาหวานจำแนกตามสิทธิบัตร แยกเป็นคน (ผู้ป่วยรายใหม่ในปี) ครั้ง (จำนวนที่มา visit) ในเครือข่าย นอกเครือข่าย ในเครือข่ายตามความหมายของผมคือว่า สถานบริการที่อยู่ในคัพของท่าน รวมถึง PCU ทุกแห่งด้วยนะ เช่น 1 โรงพยาบาล 4 สถานีอนามัย ถือเป็นในเครือข่ายทั้งหมด (เอามาคิดเฉพาะ hospmain นะครับ ) วิธีการของผมคือสร้างเป็นตารางฝังไว้ใน Hospital OS อีกหนึ่งตาราง รายละเอียดก็ไม่มากมายอะไร สามารถดรอปทิ้งได้เมื่อเบื่อหน่าย ก้าย เซ็ง วิธีการสร้างก็คือ เอาชื่อว่า r_service_incup แล้วกันนะครับ มีอยู่ฟิลด์เดียวแค่นั้น&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;CREATE TABLE service_cup&lt;br /&gt;(&lt;br /&gt;  off_code varchar&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;แล้ววิธีการเอารหัสสถานบริการใส่คือ&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;INSERT INTO service_cup VALUES ('99999');&lt;/pre&gt;&lt;br /&gt;เมื่อ 99999 คือรหัสสถานพยาบาลที่อยู่ในคัพของท่านเองนะ แล้วอีกตารางหนึ่งที่ต้องเพิ่มเข้าไปคือ r_village_inpcu (รายชื่อหมู่บ้านที่อยู่ในเขตรับผิดชอบของ PCU โรงพยาบาล) มีอยู่ด้วยกัน 3 ฟิลด์ดังนี้&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;CREATE TABLE r_village_inpcu&lt;br /&gt;(&lt;br /&gt;  village_code varchar,&lt;br /&gt;  village_name varchar,&lt;br /&gt;  tambon varchar(255)&lt;br /&gt;)&lt;/pre&gt;&lt;br /&gt;โดยที่ village_code คือเลขหมู่บ้านคือ 1,01 2,02 ....10,11 เหตุที่ต้องมี 01,02 .... 09 ก็เพราะว่าเวลาทำบัตรอาจจะไม่ได้กรอกข้อมูลเป็น 1 อาจกรอกเป็น 01 ก็ได้ใครจะรู้ถ้าเราเอาแค่ 1 แล้วคนที่ถูกกรอกเป็น 01 ก็จะ loss ไป หรือจะเพิ่มเป็น 001,002 ..... 009 ก็ได้นะครับ ไม่ว่ากัน ส่วนเจ้า village_name คือชื่อหมู่บ้านนั่นเอง เช่น บ้านทุ่งสุนัขไม่แล บ้านดอนน้ำท่วม ๆลๆ ก็ว่ากันไป ส่วนฟิลด์สุดท้ายคือ tambon คือรหัสตำบลที่หมู่บ้านเหล่านี่ตั้งอยู่ หาได้โดยการดูที่ f_address_id จากตาราง f_address นะครับ จะมีอยู่ด้วยกัน 6 หลัก 2 หลักแรกคือรหัสจังหวัดเช่นลำพูน มีรหัสนำหน้าด้วย 51 อีกสองหลักต่อมาเป็นรหัสอำเภอ เช่นทุ่งหัวช้าง ก็เป็น 5105 สองหลักสุดท้ายคือรหัสตำบลนะครับ เช่นตำบลทุ่งหัวช้างก็จะมีรหัสเป็น 510501 วิธีการดูจากตาราง f_address คือ สมมติว่าผมอยากทราบว่า อำเภอทุ่งหัวช้างมีกี่ตำบลอะไรบ้างก็อาจจะคิวรี่ด้วย คำสั่ง&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT * FROM f_address WHERE address_amphur_id like '5105%' AND address_tambon_type='3'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ก็จะได้คำตอบแบบนี้&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;f_address_id     address_description     address_tambon_type     address_amphur_id     address_changwat_id     address_region&lt;br /&gt;510501     ทุ่งหัวช้าง     3     510500     510000     10&lt;br /&gt;510502     บ้านปวง     3     510500     510000     10&lt;br /&gt;510503     ตะเคียนปม     3     510500     510000     10&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;รายงานที่แก้ไข&lt;br&gt;&lt;br /&gt;  มีดังนี้&lt;br /&gt;  &lt;ol&gt;&lt;br /&gt;   &lt;li&gt;รายงานแสดงจำนวนของผู้ป่วยโรคเรื้อรังจำแนกตามเขตบริการ (pcu) ,ในเครือข่าย ,นอกเครือข่าย รายคน/ครั้ง&lt;/li&gt;   &lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;รายงานที่เพิ่มใหม่&lt;br&gt;&lt;br /&gt;  มีดังนี้&lt;br /&gt;  &lt;ol&gt;&lt;br /&gt;   &lt;li&gt;รายงานแสดงจำนวนของผู้ป่วยด้วยโรคเบาหวานและความดันโลหิตสูงแยกคนครั้ง จำแนกตามสิทธิบัตร&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;br /&gt;  ไฟล์ที่เกี่ยวข้อง&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ในรูทของ HospitalOSReport&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;showReport_ChronicGroup_2.php&lt;span style="color: rgb(255, 0, 0);"&gt; (แก้ไขใหม่)&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_DMHT_2.php&lt;span style="color: rgb(255, 0, 0);"&gt;  (เพิ่มเติม)&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ใน HospitalOSReport/inc&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;showReport_ChronicGroup.inc.php&lt;span style="color: rgb(255, 0, 0);"&gt;  (แก้ไขใหม่)&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_ChronicGroup_2.inc.php&lt;span style="color: rgb(255, 0, 0);"&gt;  (แก้ไขใหม่)&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_DMHT.inc.php&lt;span style="color: rgb(255, 0, 0);"&gt;  (เพิ่มเติม)&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_DMHT_2.inc.php&lt;span style="color: rgb(255, 0, 0);"&gt;  (เพิ่มเติม)&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;listReport_CaseChronicParameter_2.inc.php&lt;span style="color: rgb(255, 0, 0);"&gt;  (เพิ่มเติม)&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;listReport_DMHTParameter_2.inc.php&lt;span style="color: rgb(255, 0, 0);"&gt;  (เพิ่มเติม)&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ใน HospitalOSReport/inc/scriptChk&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;chkInputDate.inc.php&lt;span style="color: rgb(255, 0, 0);"&gt;  (แก้ไขใหม่)&lt;/span&gt;&lt;li&gt;&lt;br /&gt;   &lt;li&gt;chkInputDate2.inc.php&lt;span style="color: rgb(255, 0, 0);"&gt;  (เพิ่มเติม)&lt;/span&gt;&lt;li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ใน HospitalOSReport/inc/SQL&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;&lt;abbr title="update07102548.sql"&gt;คำสั่งในการ INSERT รายงานเข้าสู่ตาราง index_report ในฐานข้อมูล user_report&lt;/abbr&gt;&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;a href=http://www.hospital-os.com/~uthai/debian-install/update/HospitalOSReport_update_07102548.zip&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ไฟล์สำหรับดาวน์โหลด&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112887948141429695?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112887948141429695/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112887948141429695' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112887948141429695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112887948141429695'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/10/update-9-2548.html' title='เวบรีพอร์ต Update 9 ตุลาคม 2548'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112827062045427610</id><published>2005-10-02T21:54:00.000+07:00</published><updated>2005-10-02T23:30:20.466+07:00</updated><title type='text'>ชื่อ นามสกุล แล้วก็การสอบ Pre Test เพื่อการเข้าอบรม dot net Programmer</title><content type='html'>สุดสัปดาห์นี้ (เสาร์ อาทิตย์) มีเรื่องมากมายที่อยากเขียน&lt;br /&gt;&lt;ol&gt;   &lt;li&gt;เรื่องแรกคือน้ำท่วมเชียงใหม่อีกครั้ง แล้วเกี่ยวอะไรกับพ้มล่ะ อ๋อก็เกี่ยวสิ ก็วันเสาร์ที่ผ่านมา ยอดชายนายเล็ก ผ.จ.ก.ดีเอส คอมพิวเตอร์นัดผมไปเอาจอใหม่ ปรากฏว่าวันศุกร์ไอ้เราก็อุตส่าห์โทรไปคอนเฟิร์มนะว่าเอาแน่ ขอให้เตรียมของให้ด้วย ได้รับคำตอบด้วยน้ำเสียงเซ็งๆ ว่าเข้าออฟฟิซไม่ได้ค๊าบบ (ออฟฟิซของนายเล็กอยู่ในหมู่บ้านเชียงใหม่แลนด์อ่ะดิ น้ำประมาณหน้าอก) ก็เลยผลัดไปเป็นอาทิตย์หน้า แล้วกัน เพื่อนฝูง หยวนๆ กันอยู่แล้ว&lt;/li&gt;   &lt;li&gt;เลยเอารถไปเช็คซะดีกว่า ที่บริษัทสยามนิสสันเชียงใหม่ เรื่องน่าเศร้าก็คือว่าน้ำที่หม้อน้ำหายเกลี้ยงไม่เหลือหลอ ก็เปลี่ยนใหม่เกือบทั้งชุด ก็นั่งรอยาวตั้งแต่แปดโมงเช้า ถึงสี่โมงเย็น ในระหว่างที่นั่งรอก็เหลือบไปเห็นหนังสือเล่มนึงพาดหัวเกี่ยวกับ โทนี่ จา  (พนม ยีรัมย์) ก็เลยสงสัยขึ้นมาว่า คุณโทนี่ เป็นคนจังหวัดบุรีรัมย์ หรือปล่าว เคยได้ยินมาว่าถ้านามสกุลลงท้ายด้วย  รัมย์ แล้วล่ะก็ มาจากบุรีรัมย์ มากกว่าครึ่ง (ประวัติ วะโฮรัมย์  นักกีฬาวีลแชร์) หรือที่มาจากอำเภอด่านขุนทด ก็จะมีนามสกุลลงท้ายด้วย ..ขุนทด (คนที่เคยเล่าให้ฟังคือ น้ำหวาน ที่พ่อของเธอ มาจากอำเภอด่านขุนทด ก็นามสกุล ชันขุนทด) สรุปตามที่เคยได้ยินเลยว่า&lt;/li&gt; &lt;/ol&gt; &lt;ul&gt;   &lt;li&gt;ลงท้ายด้วย ....กาศ  พื้นเพมาจาก ตำบลทากาศ อ.แม่ทา จ.ลำพูน (หะกาศ ตุ้ยกาศ ปันกาศ ยะกาศ)&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;ลงท้ายด้วย ...ไธสงค์  พื้นเพมาจาก อ.พุทไธสงค์ จ.บุรีรัมย์&lt;/li&gt;   &lt;li&gt;ลงท้ายด้วย ...ขุนทด พื้นเพมาจาก อ.ด่านขุนทด จ.นครราชสีมา&lt;/li&gt;   &lt;li&gt;ลงท้ายด้วย ....โมงค์ พื้นเพมาจาก ต.อุโมงค์ อ.เมือง จ.ลำพูน (ปิ่นอุโมงค์ อุดอุโมงค์ พันธ์อุโมงค์)&lt;/li&gt;   &lt;li&gt;ลงท้ายด้วย ....พิงค์ พื้นเพมาจาก ต.ริมปิง อ.เมือง จ.ลำพูน เนื่องจาก ต.ริมปิงนี่ตั้งอยู่ริมแม่น้ำปิง สันนิษฐานได้ว่า คำว่าพิงค์ อาจจะเพี้ยนมาจาก ปิง นั่นเอง&lt;/li&gt; &lt;/ul&gt; อ่าทีนี้เริ่มคิดเลยเถิดไปเมืองนอกบ้างแล้ว  เฮ่อ ๆๆ (ฟุ้งซ่านเอามากๆ)  ยกตัวอย่าง เช่น&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;ชาวเยอรมัน มักจะมีนามสกุลลงท้่ายด้วย ....er ( โมลเลอร์ , มุลเลอร์ , โฟลเลอร์ , เบคเคนบาวเอ้อร์ , เอาเก้นทาเลอร์ , ชไวน์สไตเกอร์ ,ชูมัคเกอร์  หรือที่รู้จักดีคือ ท่าน แกร์ฮาร์ด ชโรเดอร์ นายกรัฐมนตรี) ผมลองนั่งนึกเล่นๆ ว่าถ้าพูดถึงชาวเยอรมัน จะนึกถึงใครเป็นคนแรก ผมนึกถึง มิชาเอล ชูมัคเกอร์แฮะ รู้สึกว่าหน้าตาเขาบ่งบอกได้เลยว่าเป็นชาวเยอร์มัน&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;ชาวเนเธอร์แลนด์ นามสกุลมักจะมีคำว่า van เช่น รุด ฟานนิสเตอรรอย , มาร์โก ฟานบาสเท่น , ฟานบอมเมล , ฟานเดอร์ซาร์) ก็นึกถึง เอ็ดวิน ฟานเดอร์ซาร์ ผู้รักษาประตูทีมแมนยู ก็แล้วกัน หน้าตาของชาวดัชต์ น่าจะเป็นแบบนั้นแหละ&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;คนสวีเดน มักจะมีนามสกุลลงท้ายด้วย ....on ( larson , peterson , nilsson , anderson) เอ ส่วนหน้าตาชาวสวีดิชเนี่ยพยายามนึกอยู่ แต่นึกไม่ออก อีกคนที่ลืมไปคือ สเวน โกรัน อิริคสัน งัย&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;ชาวเดนมาร์กบ้าง ก็จะลงท้ายด้วย ...sen ( polsen , jorgensen , nilsen) ส่วนหน้าตาก็นึกไม่ออกเหมือนกัน&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;ชาวฟินแลนด์ ก็มักจะลงท้ายด้วย ....nen (มิก้า ฮ้คคีเนน , ยารี่ ลิตมาเนน , หรือคนที่มาแข่งเทนนิส Bangkok thailand open invitation ที่นามสกุล naminen)&lt;/li&gt;   &lt;li&gt;ชาวอิตาเลี่ยนบ้าง ก็มักจะลงท้ายด้วย   ...i ( เช่น ซิลวิโอ แบร์ลุสโคนี่ , เปาโล รอสซี่ , อัลแบร์ตินี่ , ต๊อดตี้ , ทัตซอสตี้ , จิอันนีนี่ ) หน้าตาก็ให้นึกถึงเปาโล รอสซี่ หรือว่า อเล็กซังโดร เดล ปิเอโร่ นั่น&lt;/li&gt;   &lt;li&gt;ชาวฝรั่งเศส บ้าง ชื่อ นามสกุลนี่นึกไม่ออก นึกออกแต่หน้า นึกถึง มิเชล พลาตินี่ก็แล้วกันนะ หรือที่ใหม่หน่อยก็คือ โรแบร์ ปิแรส (ผู้เล่นทีมอาร์เซนอล )&lt;/li&gt;   &lt;li&gt;ชาวอังกฤษล่ะ หน้าตาเป็นอย่างไร ผมนึกออกอยู่สองสามคน ที่พอจะสื่อได้ว่าเป็นชาวเกาะนะ คนแรกคือ คนที่แสดงเป็น มิสเตอร์บีน งัยครับ ไม่รู้ว่าชื่อจริงว่าอะไร หรือจะดู แกรี่ เนวิลล์ ก็ได้ ปีเตอร์ เบรียดสลีย์ (อดีต ผู้เล่นทีมลิเวอร์พูล) ก็ได้ หรือยังนึกไม่ออก ก็ดูหน้า มกุฏราชกุมารนั่นแล แล้วก็นิยมตั้งชื่อแรกด้วยคำว่า ปีเตอร์ กับ แกรี่ ด้วยแหละ หลายปีก่อนอ่าน สตาร์ซอคเกอร์ แล้วคุณ ย โย่ง (เอกชัย นพจินดา เสียชีวิตไปแล้ว ) แกก็ลองเอาผู้เล่นอังกฤษที่มีชื่อขึ้นต้นด้วย แกรี่ เนี่ยมาแบ่งทีมแข่งกัน ได้สองทีม ครบทุกตำแหน่งด้วยล่ะ แปลกไหม&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;ชาวบัลแกเรีย มักจะลงท้ายด้วย ....cov คอฟ  เช่น สตอยคอฟ บาลาคอฟ เลชคอพ&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;ชาวโรมาเนี่ยน มักจะลงท้ายด้วย ....eu (คู) เช่น โปเปสคู ยอร์ดานเนสคู ลูเปสคู&lt;/li&gt;   &lt;li&gt;ชาวรัสเซีย เนี่ยมีมาก ตั้งแต่ ...ov (กอร์บาชอพ )  ....a (ชาราโปว่า ,คูนิโคว่า , สกาย่า )  ..o ( เชพเชงโก )&lt;/li&gt;   &lt;li&gt;ชาวยูโก  พวกนี้มักจะมีนามสกุลลงท้าย ด้วย ...ic (ลูคิก , สตอยโกวิช , อิวานิเซวิช , บรานิช ) แล้วก็ชอบตั้งชื่อแรกลงท้ายด้วย เมียร์ โบบัน โบดัน ขึ้นต้นด้วย สโล สโว&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;ชาวกรีก ก็มักจะลงท้ายด้วย ออส ดิส แล้วก็ยาวมากกกกกกก จนจำไม่ค่อยได้&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;ที่พูดๆ มานี่เป็นเพียงข้อสังเกตุส่วนตัวนะครับ ไม่มีสถิติมาอ้างอิงหรอก ใครสังเกตุเห็นอย่างอื่นมากกว่านี้ ก็มาแจมกันนะครับ ;-)&lt;/li&gt; &lt;/ul&gt;     เรื่องสุดท้ายคือไปสมัครเข้ารับการอบรมเกี่ยวกับการเขียนโปรแกรม dot net ไว้แล้ววันนี้เค้าเรียกไปทำ Pre Test เพื่อวัดความรู้ (&lt;a href=http://www.sipachiangmai.org&gt;www.sipachiangmai.org&lt;/a&gt; กับ &lt;a href=http://www.northern.co.th&gt;www.northern.co.th&lt;/a&gt;) การอบรมนี่ฟรีครับ เพื่อเป็นพื้นฐานในการไปสอบเซอร์ MCAD (Microsoft Certified Application Developer) ผมเองไม่ได้มีความตั้งใจจะไปสอบเซอร์กับเค้าหรอก แต่อยากเรียนเพื่อรู้เกี่ยวกับการเขียนโปรแกรมแบบ OOP ต่างหาก แต่หาคอร์สเรียนไม่ลงตัว (ที่ฟรีและใกล้บ้าน อิ อิ) และเป็นพื้นฐานในการจับกับ จาวา มากกว่า (เค้ารู้เค้าจะโกรธไหมเนี่ย) การสอบวัดความรู้ปรากฏว่าผมไม่ค่อยรู้เรื่อง เนื่องจากไม่มีพื้นของ OOP มาก่อนประกอบกับเราำไม่ได้เรียนมาทางคอมพิวเตอร์โดยตรง และข้อสอบเป็นภาษาอังกฤษทั้งหมด แต่ก็พอเดาๆ ได้ว่าข้อสอบเค้าต้องการอะไร แต่ก็ทำอะไรมากไม่ได้ นอกจาก เดา เดา ไปให้ครบ 14 ข้อ พรุ่งนี้ประกาศผลสอบแล้ว ลุ้นผมหน่อยแล้วกัน ถ้าผมโชคดีเดาถูก 55555 แต่ก็มีคนออกห้องสอบก่อนผมเยอะนะ ประมาณ 5 นาทีก็มีคนออกห้องสอบแล้ว ทำเอาผมรู้สึกว่าตัวเล็กไปถนัดใจ ไม่รู้ว่ามันง่ายเกินไปหรือปล่าว หรือมองเข้าข้างตัวเองว่า คนที่ออกก่อนน่ะ มั่วนิ่ม  อารายฟะ มรึงอ่านภาษาอังกฤษ 5 กระดาษ A 4 ภายในเวลา 5 นาทีเองเหรอ (พยายามคิดเข้าข้างตัวเองมากไปมั๊ง) โจทย์ก็ออกมาประมาณว่ากำหนดค่าอะไรมาให้แล้วก็ถามว่า ถ้าต้องการดีบัก ให้แก้ไขอะไร ตรงบรรทัดไหน หรือว่า การกำหนดค่าตัวแปรของออปเจ็กค์เนี่ยกำหนดจากไหน อืมจำได้แค่นี้ ที่ตลกมากคือคนออกข้อสอบคงจะรีบมาก เลยออกข้อสอบแค่ 14 ข้อ ข้อ 7 ไม่มี แล้วข้อ 4 กับข้อ 10 ยังเป็นข้อสอบข้อเดียวกันอีกต่างหาก เออ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112827062045427610?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112827062045427610/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112827062045427610' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112827062045427610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112827062045427610'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/10/pre-test-dot-net-programmer.html' title='ชื่อ นามสกุล แล้วก็การสอบ Pre Test เพื่อการเข้าอบรม dot net Programmer'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112767042525308144</id><published>2005-09-26T00:41:00.000+07:00</published><updated>2005-09-26T00:47:05.263+07:00</updated><title type='text'>โจทย์ที่ไม่น่ายาก แต่คิดหาที่ทำแล้วเจ๋งๆ ยังไม่เจออ่ะ</title><content type='html'>สืบเนื่องจากอาทิตย์ก่อน อาจารย์ที่ปรึกษาจาก &lt;a href=http://www.ha.or.th&gt;พ.ร.พ&lt;/a&gt; ได้มาเยี่ยมประเมินสภาพความพร้อม เพื่อขอรับการ Accredit แต่ละทีมก็ได้รับคำแนะนำที่เป็นประโยชน์หลายประการ ประเด็นหนึ่งซึ่งเกี่ยวข้องโดยตรงกับผม ซึ่งมีส่วนร่วมในส่วนของ IM และงานบริการในห้องยา เรื่องที่พูดถึงก็คือการลดความซ้ำซ้อนในการคัดลอกคำสั่งแพทย์ในตึกผู้ป่วยใน ปกติแล้วเวลาแพทย์เข้าไปติดตามอาการของผู้ป่วยเพื่อพิจารณาสั่งการรักษาประจำวัน หรือที่เรียกกันในวงการว่า Round Ward จะมีเอกสารที่สำคัญมากอยู่แผ่นนึงคือ Doctor Order (ขนาดประมาณ A4) แบ่งเป็นสองฟากซ้าย ขวา ฟากซ้ายเป็น Order For Oneday อีกฟากหนึ่งเป็น Order Continue (อาจจะพูดมากไปหน่อย เนื่องจาก Blog ของเราอยู่บนเครือข่ายอินเทอร์เน็ต อาจจะมีเพื่อนใหม่ ที่ไม่ได้อยู่ในวงการสาธารณสุข เข้ามาอ่าน จำเป็นต้องพูดให้ละเอียดนิดนึง) เจ้าเอกสารแผ่นนี้สำคัญมาก ชนิดที่ว่าหายไม่ได้ (ความจริงเอกสารเกี่ยวกับผู้ป่วยนี้ก็สำคัญทุกแผ่นนะ) ปกติแล้ว หลังจากแพทย์ Round Ward เสร็จก็จะทำการสั่งการรักษาลงใน Order Doctor หน้าที่ของผมคือ อ่านเจ้า Order Doctor นี้ทุกวัน ทุกรายที่เป็นผู้ป่วยใน เพื่อที่จะบันทึกข้อมูลเหล่านี้ลงใน &lt;a href=http://www.hospital-os.com&gt;Hospital OS&lt;/a&gt; ส่งรายการไปที่ห้องยาเพื่อจัดยาให้ผู้ที่มาใช้บริการ (เป็นศัพท์ใหม่ที่ควรจะใช้ แทนคำว่าผู้ป่วย หรือ ผู้มารับบริการ ฟังดูแล้วรู้สึกว่าเราเป็นผู้ให้บริการนะ หรูขึ้นไปอีก) พร้อมกับแนบเจ้า Order Doctor ไปด้วยเพื่อที่เภสัชกรจะได้ทำการตรวจสอบว่า รายการที่เบิกมาถูกต้องตามคำสั่งแพทย์จริงๆ หรือปล่าว ก่อนที่จะทำการส่งมอบยากลับมาที่ตึก หรือจ่ายให้ผู้มาใช้บริการกลับไปทานต่อที่บ้าน ทีนี้ปัญหาอยู่ที่ว่าเจ้า Order Doctor นี่ตามหลักการแล้วไม่ควรจะถูกเคลื่อนย้ายออกจากตึก เนื่องจากเหตุผลด้านความปลอดภัย  สะดวกในการบันทึกกรณีที่มีเหตุฉุกเฉินต้องรายงานแพทย์ และเป็นการพิทักษ์สิทธิ์ของผู้ป่วยด้วย (การรักษาความลับของผู้ป่วย) โจทย์ที่ผมได้รับคือทำอย่างไรถึงจะไม่ต้องแนบเอกสารนี้ออกไปให้เภสัชกรตรวจสอบ แต่เภสัชกรก็ต้องสามารถที่จะเห็นลายมือแพทย์ได้โดยตรง&lt;br&gt;&lt;br /&gt;โอ จอร์ช มันยอดมากเลย คิดออกอยู่ สองวิธีที่น่าจะเข้าท่า คือ&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;1. ก็สอดกระดาษเข้าไปข้างใต้ Order Doctor หลังกระดาษคาร์บอนซะ ทีนี้พอแพทย์เขียนอะไรบน Order Doctor มันก็จะถูกสำเนาลงมาบนกระดาษที่เราสอดไว้อยู่แล้ว (นอกจากว่าลืมสอดกระดาษคาร์บอน) เห่อ เห่อ เราก็เอากระดาษที่สำเนาได้น่ะ ส่งไปแทนซะ &lt;/li&gt;&lt;br /&gt; &lt;li&gt;2. สแกน Order Doctor มันซะเลย เครื่องสแกนที่โรงพยาบาลก็มีเอามาใช้ให้มันคุ้มค่า ไม่ต้องใช้กระดาษให้มันยุ่งยาก&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;เสนอความคิดเห็น ผ่านหัวหน้าฝ่ายไปคุยกับ ผู้อำนวยการแล้ว ได้รับโจทย์ให้มาคิดเพิ่มอีกว่า หาวิธีการทำตามแบบที่สองให้หน่อย รู้สีกว่ามันเข้าท่า ไม่ต้องเปลืองกระดาษ ลดความคลาดเคลื่อนในการอ่านลงไป (ข้อนี้หัวหน้าผม กับหัวหน้าตึก ร่วมมือกันไปล๊อบบี้) เกิดว่ากระดาษคาร์บอนเก่าก็จะทำให้สำเนาไม่ชัด ต้องมีการสอบถามกลับอีกเสียเวลา และไม่มีใคร(พยาบาลในตึก) ว่างมากถึงขนาดที่ต้องมานั่งจัดการเรื่องการสอดกระดาษเข้าๆ ออกๆ เตรียมให้คุณ ! แป่ว ไปหาวิธีจัดการให้ได้ เร็วที่สุด ไม่ต้องรอฟีเจอร์ใหม่ของ Hospital OS ทำไปก่อนก็ได้ หากโปรแกรมได้รับการพัฒนาแล้วค่อยว่ากันอีกที &lt;br&gt;&lt;br /&gt;เอ แล้วเราจะจัดการได้อย่างไรดีนะ ให้มันสะดวกทั้งเรา และทั้งเค้า ต้องมีระบบรักษาความปลอดภัยด้วยนะ เพราะนี่คือความลับของผู้ป่วย (ผู้ใช้บริการ แต่ผมมักติดปากเรียกเค้าว่าผู้ป่วยอยู่)&lt;br&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;ซอพท์แวร์ที่ใช้ก็ต้องเป็นซอพท์แวร์เสรี นึกถึง &lt;a href=http://www.picasa.com&gt;Picasa&lt;/a&gt; ขึ้นมาได้แต่คงต้องไปดูอีกทีว่ามีฟีเจอร์ที่ Connect กับ Scanner ได้หรือปล่าว&lt;/li&gt;&lt;br /&gt; &lt;li&gt;พอได้ซอพท์แวร์แล้วก็สแกนลงใน ThumbDrive พอเราไปถึงห้องยาก็เอาไปเสียบก็สามารถดูภาพได้ บรรเจิดเลยทีนี้ ใครก็ไม่มีทางรู้เห็นภาพได้ แต่ถ้าเกิดมีออเดอร์เพิ่มล่ะ กรูมิต้องวิ่งเข้าวิ่งออก ระหว่างตึกกะห้องยาหรือฟะ เป็นอันว่าไอเดียนี้ไม่สะดวกกับเราแน่ๆ&lt;/li&gt;&lt;br /&gt; &lt;li&gt;นึกออกอีกอย่างนึงแล้วล่ะ ว่าเราก็สร้างโฟลเดอร์ไว้ในเครื่องที่ห้องยาซะ แล้วก็แชร์แบบมีพาสเวอร์ด ให้เฉพาะเครื่องที่ตึกสามารถเข้าถึงได้ เออดูคิดเป็นผู้เป็นคนกะเค้าหน่อย เอาน่าใช้แบบนี้ไปก่อนละกัน แล้วค่อยไป search หา Solution ที่เจ๋งในเน็ตอีกที&lt;/li&gt;&lt;br /&gt; &lt;li&gt;ว่าจะลองไป search ใน &lt;a href=http://sourceforge.net&gt;Sourceforge dot net&lt;/a&gt; ดูซอพท์แวร์ที่น่าจะช่วยเหลือเรื่องนี้ได้ ใครพอมีไอเดีย หรือเคยเห็นว่าการทำอย่างนี้ มีทางที่สะดวกและเหมาะสมกับผู้ที่คุ้นเคยกับคอมพิวเตอร์ไม่มากนัก (พยาบาลในตึก) ที่ต้องทำเองในวันหยุดได้ หรือวันอื่นๆ ที่ผมไปทำหน้าที่ไม่ได้ ก็แนะนำผมด้วยนะครับ&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112767042525308144?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112767042525308144/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112767042525308144' title='2 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112767042525308144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112767042525308144'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/09/blog-post_26.html' title='โจทย์ที่ไม่น่ายาก แต่คิดหาที่ทำแล้วเจ๋งๆ ยังไม่เจออ่ะ'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112766032020688860</id><published>2005-09-25T21:55:00.000+07:00</published><updated>2005-09-25T21:58:40.206+07:00</updated><title type='text'>เวบรีพอร์ต Update 25 กันยายน 2548</title><content type='html'>เรื่องมีอยู่ว่า พึ่งไปเห็นว่ามีรายงานแสดงสถานะของผู้ป่วยในด้วยว่า ในช่วงเวลาหนึ่งๆ นั้นมี รับใหม่ จำหน่ายไปกี่คน แยกตามสิทธิบัตร ด้วยแต่บังเอิญไปทำให้มันไม่ Active ซะอย่างนั้น (น่าเบิด) ก็เลยเข้าไปดู เออเข้าท่าแฮะ แต่อ่าน SQL แล้วปวดหัวเป็นบ้า ก็เลยทำการโมดิฟายใหม่ เอาให้ (ตัวเอง) อ่านง่ายอีกหน่อยและเพิ่มความสามารถในการแสดงจำนวนวันนอนออกมา และยังสามารถลิงค์ไปดูรายละเอียดของตัวเลขแต่ละค่าที่แสดงออกมาด้วยล่ะ ซึ่งน่าจะทำให้มองภาพรวมได้ชัดเจนขึ้น ในอาทิตย์ที่ผ่านมานั้นเป็นสัปดาห์ในการทำงานที่ค่อนข้างจะเหนื่อย เนื่องจากเป็นอาทิตย์ที่มี คนประจำการห้องยาน้อยกว่าปกติ น้องๆ เค้าไปดุงานกัน ที่จริงแล้วผมก็อยู่ในลิสต์ที่จะได้ไปนะ แต่ขอตัวไม่ไป แล้วอาจารย์ที่ปรึกษามาเยี่ยมด้วย ทำให้ต้องรีบหาผักชีมาโรยกันใหญ่ ผลก็คือยังไม่สามารถขอ Accredit ได้ภายในสิ้นปีนี้ ซึ่งค่อนข้างจะทำให้ทีมงานบางท่าน เข่าอ่อนไปเนื่องจาก มั่นใจว่าน่าจะเข้าตากรรมการ หึหึ ก็ต้อง ICV (เข้ม) ต่อไปอีก วันพฤหัสบดี กับวันศุกร์ที่ผ่านมา อยู่กับหัวหน้าฝ่ายเพียงสองคน (สองคนจริงๆ นะ) คิดดูว่าโรงพยาบาลทั้งโรงพยาบาล มีคนอยู่ในห้องยาเพียงสองคน ข้าวกลางวันไม่ต้องพูดถึงครับ เป็นอะไรที่เหนื่อยมั่กมาก สาธุอย่าให้เจอเหตุการณ์แบบนี้อีกเลยนะ สาบานได้ว่าความเสี่ยงที่เกิดขึ้นน่ะมันมาก ปริมาณงานที่มาก ในขณะที่มีคนทำงานน้อย แล้วต้องทำเกือบทุกอย่าง เพื่อให้การประกันคุณภาพเท่าเดิม ดีที่ไม่มีอุบัติการณ์เกิดขึ้น ก็โชคดีของผู้มาใช้บริการไป&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;รายงานที่เพิ่ม&lt;br&gt;&lt;br /&gt;  มีดังนี้&lt;br /&gt;  &lt;ol&gt;&lt;br /&gt;   &lt;li&gt;รายงานแสดงสถานะของผู้ป่วยในทั้งหมด&lt;/li&gt;   &lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;br /&gt;  ไฟล์ที่เกี่ยวข้อง&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ในรูทของ HospitalOSReport&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;showReport_IPDStatus_2.php&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ใน HospitalOSReport/inc&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;showReport_IPDStatus.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_IPDStatus_2.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;listReport_IPDStatus_Admit_2.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;listReport_IPDStatus_Discharge_2.inc.php&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;a href=sql/showReport_IPDStatus.sql&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;คำสั่งในการ INSERT รายงานเข้าสู่ตาราง index_report ในฐานข้อมูล user_report&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;a href=update/webreport_update_25092005.zip&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ไฟล์สำหรับดาวน์โหลด&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112766032020688860?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112766032020688860/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112766032020688860' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112766032020688860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112766032020688860'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/09/update-25-2548.html' title='เวบรีพอร์ต Update 25 กันยายน 2548'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112766004074242360</id><published>2005-09-19T21:51:00.000+07:00</published><updated>2005-09-25T21:54:40.900+07:00</updated><title type='text'>เวบรีพอร์ต อัพเดท 19 กันยายน 2548</title><content type='html'>สุดสัปดาห์ที่ผ่านมา อากาศแจ่มใส ทำให้รู้สึกกระชุ่มกระชวยขึ้น มีสมาธิในการทำงานดีทีเดียว ถึงแม้ว่าจะถูก Interrupt จากเด็กๆ บ้างแต่รวมๆ แล้วก็ดี นั่งเพิ่มฟีเจอร์ของรายงานโรคเรื้อรังรายกลุ่มได้ แม้ว่าช่วงหลังๆ จะต้องออกแรงเยอะหน่อยนึง&lt;br&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;สิ่งที่เพิ่มขึ้นมาใหม่ในรายงาน โรคเรื้อรังรายกลุ่มคือ การทำให้หน้าเพจสามารถแสดงรายละเอียดของผู้ป่วยได้ โดยการคลิกที่ &lt;span style="color: rgb(255, 0, 0);"&gt;ดูรายละเอียด&lt;/span&gt; ก็จะทำการส่งค่าพารามิเตอร์ไปให้อีกเพจหนึ่งทำการประมวลผลให้&lt;br /&gt;  &lt;ol&gt;&lt;br /&gt;   &lt;li&gt;ไฟล์ที่แก้ไขคือ inc/showReport_ChronicGroup_2.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;ไฟล์ที่สร้างใหม่ คือ inc/listReport_CaseChronicParameter_2.inc.php&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;สิ่งที่ต้องแก้ไข ปรับปรุง&lt;br /&gt;  &lt;ol&gt;&lt;br /&gt;   &lt;li&gt;ตาราง disease_chronic จะถูกเปลี่ยนชื่อเป็น r_disease_chronic จากการที่ได้คุยกับ ojika ว่าตารางที่ทำเพิ่มขึ้นมาใหม่เพื่อใช้ในการช่วยออกรายงานนั้นควรจะตั้งชื่อให้สอดคล้อง และเหมาะสมก็เลยลงเอยว่าเอาขึ้นต้นด้วย r_ ก็แล้วกัน&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;ตาราง disease_chronic_code จะถูกเปลี่ยนชื่อเป็น r_disease_chronic_code&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;ความจริงแล้วตารางสองตารางใหม่นี้ก็คือตารางอันเดิมนั่นแหละ เพียงแต่เปลี่ยนชื่อใหม่แค่นั้นเอง แต่ก็ต้องทำการสร้างใหม่ด้วยนะ เสร็จแล้วถึงค่อยไปดรอป disease_chronic กับ disease_chronic_code ได้ และด้วยแนวคิดที่ได้กล่าวถึงข้างบนมาแล้ว จะทำให้เกิดการเปลี่ยนแปลงอีกหลายเพจ เนื่องจากจะต้องเปลี่ยนชื่อตารางใหม่ ก็คอยติดตามกันไป&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt; &lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;วิธีการสร้างตารางใหม่อีก 2 ตาราง&lt;br /&gt;  &lt;ol&gt;&lt;br /&gt;   &lt;li&gt;อัพโหลดไฟล์ r_disease_chronic.sql และ r_disease_chronic_code.sql ขึ้นไปไว้บนเซอร์เวอร์&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;&lt;pre class=command&gt;postgres@host:~$ psql your_database &lt; r_disease_chronic.sql&lt;br&gt;&lt;br /&gt;postgres@host:~$ psql your_database &lt; r_disease_chronic_code.sql&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;แล้วทีนี้ก็ลบตาราง disease_chronic กะ disease_chronic_code ได้ วิธีการก็แล้วแต่ถนัดละกัน&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;ไฟล์สำหรับดาวน์โหลด อยู่ &lt;a href=update/webreport_update19092005.zip&gt;ที่นี่ครับ&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112766004074242360?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112766004074242360/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112766004074242360' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112766004074242360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112766004074242360'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/09/19-2548.html' title='เวบรีพอร์ต อัพเดท 19 กันยายน 2548'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112697228609430046</id><published>2005-09-17T22:47:00.000+07:00</published><updated>2005-09-25T21:49:07.653+07:00</updated><title type='text'>เวบรีพอร์ต Update แล้ว (patch level 1)</title><content type='html'>พึ่งได้รับการ Feed Back จากยูสเซอร์อย่างเป็นเรื่องเป็นราว เมื่อวันศุกร์ที่ผ่านมานี้เองว่า รายงานแสดงสถานะของผู้ป่วยในทั้งหมด นั้นหน่ะยังไม่ถูกใจ ว่างั้น ก็ถามว่าเป็นอย่างไร ต้องการอะไรเพิ่มเติม ก็อายุแสดงไม่ครบอ่ะเด่ มีแต่ ปี ขาด เดือน กะวันไป เพิ่มให้หน่อยแล้วเธอ ก็จากปายยยย&lt;br&gt;&lt;br /&gt;อ๋อได้ จัดให้ จะไปยากอะไร ก็เพียงแต่เปลี่ยนฟังก์ชั่นที่ใช้ในการคำนวณอายุ จาก calage3 เป็น calage2 ซะก็สิ้นเรื่อง เจ้า calage2 นี้ก็ได้รับความอนุเคราะห์จากสุรชัย ต่อวงศ์อีกแล้วเขียนให้ ต้องขอขอบใจในความเอื้ออาทรอีกครั้ง เป็นฟังก์ชั่นที่รับค่าพารามิเตอร์มาสองค่าคือ &lt;span style="color: rgb(255, 0, 0);"&gt;t_visit.visit_begin_visit_time กับ t_patient.patient_birthday&lt;/span&gt; แล้วก็เอาไปคำนวณรีเทอร์นค่าออกมาเป็นเทกซ์ (ปี เดือน วัน) หน้าตาเป็นอย่างนี้ครับ&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;CREATE OR REPLACE FUNCTION calage2(date, date)&lt;br /&gt;  RETURNS text AS&lt;br /&gt;'&lt;br /&gt;DECLARE&lt;br /&gt;         mm INTEGER := 0;&lt;br /&gt;         dd INTEGER := 0;&lt;br /&gt;&lt;br /&gt;  y INTEGER := 0;&lt;br /&gt;  m INTEGER := 0;&lt;br /&gt;  d INTEGER := 0;&lt;br /&gt;  &lt;br /&gt;  age TEXT := \'\';&lt;br /&gt; BEGIN&lt;br /&gt;         dd := $1-$2;&lt;br /&gt;&lt;br /&gt;  IF ( dd&gt;365 OR dd=365 )&lt;br /&gt;  THEN &lt;br /&gt;      y := dd/365;&lt;br /&gt;  ELSE &lt;br /&gt;      y := 0;&lt;br /&gt;         END IF;&lt;br /&gt;&lt;br /&gt;  mm := dd-y*365;&lt;br /&gt;  &lt;br /&gt;  IF ( mm&gt;30 OR mm=30 )&lt;br /&gt;  THEN &lt;br /&gt;      m := mm/30;&lt;br /&gt;  ELSE &lt;br /&gt;      m := 0;&lt;br /&gt;         END IF;&lt;br /&gt;&lt;br /&gt;  d := mm-m*30;&lt;br /&gt;&lt;br /&gt;  IF y &gt; 0&lt;br /&gt;  THEN &lt;br /&gt;      age := y|| \' ปี \';&lt;br /&gt;  END IF;&lt;br /&gt;&lt;br /&gt;  IF m &gt; 0&lt;br /&gt;  THEN &lt;br /&gt;      age := age||(m|| \' เดือน \');&lt;br /&gt;  END IF;&lt;br /&gt;&lt;br /&gt;  IF d &gt; 0&lt;br /&gt;  THEN &lt;br /&gt;      age := age||(d|| \' วัน \');&lt;br /&gt;  END IF;&lt;br /&gt;&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;IF d = 0&lt;br /&gt;  THEN &lt;br /&gt;      age := age||(d|| \' วัน \');&lt;br /&gt;  END IF;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;         RETURN age;&lt;br /&gt;END;&lt;br /&gt;&lt;br /&gt;'&lt;br /&gt;  LANGUAGE 'plpgsql' VOLATILE;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ส่วนวิธีการอัพเดทคือ&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;ดาวน์โหลดฟังก์ชั่น calage2 ได้ &lt;a href=sql/calage2.fnc.sql&gt;&lt;font style=bold&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ที่นี่&lt;/span&gt;&lt;/font&gt;&lt;/a&gt;&lt;/li&gt;&lt;br /&gt; &lt;li&gt;upload function ขึ้นไปบนเซอร์เวอร์ โดยวิธีไหนก็ได้&lt;/li&gt;&lt;br /&gt; &lt;li&gt;ยัดฟังก์ชั่นเข้าไปในฐานข้อมูล โดย&lt;br&gt;&lt;br /&gt; &lt;pre class=command&gt;postgres@host:/home/postgres $ psql your_database &lt; calage2.fnc.sql&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt; &lt;li&gt;สำหรับท่านที่นึกไม่ออกว่ามีฟังก์ชั่นนี้อยู่แล้วหรือไม่ก็ไม่ต้องเป็นห่วงอะไรนะครับ เพราะว่าถ้ามีแล้วก็จะทำการอัพเดทให้ แต่ถ้าไม่มีก็จะสร้างใหม่ให้เลย แต่แนะนำให้ทำการอัพเดทซะเนื่องจากว่ามีการแก้ไขเพิ่มเติมอีกเล็กน้อยตามตัวแดง ที่เพิ่มเข้าไป เนื่องจากว่าทดสอบแล้วพบว่าทารกแรกคลอดที่บันทึกวันเดือนปีเกิดเป็นวันเดียวก็บที่ admit เข้าไป ถ้าเป็น calage2 ตัวเดิมอายุจะไม่แสดงออกมา (Bug) จึงต้องเพิ่มเงื่อนไขเข้าไปอีก 3-4 บรรทัดเพื่อให้การคำนวณอายุมีความเที่ยงตรงยิ่งขึ้น&lt;/li&gt;&lt;br /&gt; &lt;li&gt;แก้ไขไฟล์ HospitalOSReport/inc/showReport_showIPD_2.inc.php อีกสี่บรรทัดดังนี้&lt;br&gt;&lt;br /&gt; จุดแรกคือบรรทัดที่ 52 เปลี่ยนจาก calage3 เป็น &lt;span style="color: rgb(255, 0, 0);"&gt;calage2&lt;/span&gt;&lt;br /&gt; จุดที่สองอยู่ทีบรรทัด 168 มีข้อความดังนี้&lt;br /&gt; &lt;pre class=file&gt;bgcolor="90AEE5" style="text-align: center;width: 50px;"&gt;อายุ&lt;/pre&gt;&lt;br /&gt; แก้ให้เป็น&lt;br /&gt; &lt;pre class=file&gt;bgcolor="90AEE5" style="text-align: center;width: &lt;span style="color: rgb(255, 0, 0);"&gt;150px&lt;/span&gt;;"&gt;อายุ&lt;/pre&gt;&lt;br /&gt; อีกสองที่คือบรรทัดที่ 234 กับ 288 แก้ตัวเลข 50 ให้เป็น 150 เหมือนกัน แต่สำหรับท่านที่ต้องการใช้อายุแบบสั้นก็ไม่จำเป็นต้องแก้ไขอะไรอีกนะครับ การแก้ไขนี้เฉพาะผู้ที่ต้องการให้การแสดงอายุเป็นแบบยาวเท่านั้น ก็เลือกกันเอาตามสะดวกนะครับ ว่าต้องการแสดงอายุเป็นแบบสั้น (calage3) หรือแบบยาว (calage2)&lt;br /&gt; &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;เห็นว่าเป็นจุดที่ค่อนข้างสำคัญก็เลยรีบมาบอกกล่าวกันตั้งแต่เนิ่นๆ เพื่อความสะดวกในการเลือกดู เลือกใช้กันน่ะครับ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112697228609430046?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112697228609430046/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112697228609430046' title='1 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112697228609430046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112697228609430046'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/09/update-patch-level-1.html' title='เวบรีพอร์ต Update แล้ว (patch level 1)'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112676527056082745</id><published>2005-09-14T01:10:00.000+07:00</published><updated>2005-09-25T21:44:38.816+07:00</updated><title type='text'>เวบรีพอร์ต Update แล้ว</title><content type='html'>ระหว่างที่นั่งรอดูบอล ลิเวอร์พูล VS รีล เบติส อยู่ก็นึกๆ ว่าน่าจะทำอะไรไปด้วยดี เอาเป็น Web Report ฉบับ Update ไปเผยแพร่เพิ่มเติมดีกว่า เห็นมีเพื่อนสมาชิกบ่นๆ กันว่าไม่ค่อยจะอัพเดทเอาซะเล๊ย เอ่อ คือว่าทำแล้วบ้าง แต่ก็แก้ไปด้วย เนื่องจากทำแล้วไม่ค่อยได้ใช้เองเท่าไหร่ ทีนี้จะถูกหรือจะผิดก็ต้องรอผลการฟีดแบคกลับมาจากผู้ใช้ ซึ่งบางทีเค้าก็ยังไม่ได้ตรวจสอบ จริงจัง บ้าง หรือฟีดแบคกลับมาแล้วแต่ก็ยังทำได้ไม่ถูกใจผู้ใช้บ้าง ก็ค่อนข้างจะเนิ่นนานไป เอาล่ะ ก็มีอยู่หลายรายงานด้วยกันที่น่าจะถูกใจผู้ใช้อยู่ เช่น&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;มีอะไรใหม่บ้าง&lt;br /&gt;  &lt;ul&gt;&lt;br /&gt;   &lt;li&gt;เลือกวันที่แบบคอมโบบ๊อกซ์ ซึ่งวันที่จะเปลี่ยนตามเดือน ตรงนี้ได้รับความอนุเคราะห์จากคุณวันเฉลิม อติวัฒนวงศ์ แห่ง IMed ช่วยเป็นธุระให้ แต่ยังไม่มีสคริปต์สำหรับเช็คค่าที่ input เข้าไปอย่างสมบูรณ์แบบนะครับ คือหมายความว่ายังคงเลือก วันสิ้นสุดน้อยกว่าวันเริ่มต้นได้อยู่ หรือว่าป้อนวันเริ่มต้นมากกว่าวันปัจจุบันได้ (bugs)&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;เพิ่ม option ต่างๆ เช่น สามารถเลือกประเภทของสถานะของรายการออเดอร์,ประเภทของรายการออเดอร์ และอื่นๆ &lt;/li&gt;&lt;br /&gt;   &lt;li&gt;เพิ่ม script สำหรับเช็คค่าจาก option ที่เลือก&lt;/li&gt;&lt;br /&gt;  &lt;/ul&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;รายงานที่เพิ่ม&lt;br&gt;&lt;br /&gt;  มีดังนี้&lt;br /&gt;  &lt;ol&gt;&lt;br /&gt;   &lt;li&gt;รายงานแสดงจำนวนผู้ป่วยด้วยโรคเบาหวานรายบุคคล&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;รายงานแสดงปริมาณและมูลค่าของยาและเวชภัณฑ์ที่จ่ายไปในแต่ละเวร&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;รายงานแสดงสถานะของผู้ป่วยในทั้งหมด&lt;/li&gt;   &lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;br /&gt;  ไฟล์ที่เกี่ยวข้อง&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ในรูทของ HospitalOSReport&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;showReport_DMHT_Case_2.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_SummaryItem_extend_2.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_ShowIPD_2.php&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ใน HospitalOSReport/inc&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;showReport_DMHT_Case.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_DMHT_Case_2.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_SummaryItem_extend.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_SummaryItem_extend_2.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_ShowIPD.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;showReport_ShowIPD_2.inc.php&lt;/li&gt;      &lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ใน HospitalOSReport/inc/option&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;option_visitType.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;option_time.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;option_payer.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;option_limit.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;option_ipd_show_date.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;option.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;option_f_order_status.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;option_f_item_group.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;option_f_diag_icd10_type.inc.php&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ใน HospitalOSReport/inc/scriptChk&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;chkOptionVisitType.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;chkOptionTime.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;chkOptionOrderStatus.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;chkOptionItemGroup.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;chkOptionIpdShowDate.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;chkOptionDiagType.inc.php&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;chkInputDate.inc.php&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ใน HospitalOSReport/js&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;dsInput.js&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt;  &lt;ol&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;Function เพิ่มเติม&lt;/span&gt;&lt;br /&gt;   &lt;li&gt;&lt;a href=sql/calage3.fnc.sql&gt;calage3.fnc.sql&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;  &lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;a href=sql/webreport_update14092005.sql&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;คำสั่งในการ INSERT รายงานเข้าสู่ตาราง index_report ในฐานข้อมูล user_report&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;a href=update/webreport_update14092005.zip&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;ไฟล์สำหรับดาวน์โหลด&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112676527056082745?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112676527056082745/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112676527056082745' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112676527056082745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112676527056082745'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/09/update.html' title='เวบรีพอร์ต Update แล้ว'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112663007413202991</id><published>2005-09-13T23:45:00.000+07:00</published><updated>2005-09-25T21:33:46.256+07:00</updated><title type='text'>เรื่องของ SQL ตอนที่ 4</title><content type='html'>ว่าจะมาเฉลยสิ่งที่เคยถามไว้ว่า ถ้าอยากจะทราบว่าในวันที่ 15 กรกฏาคม 2548 มีผู้ป่วยนอกมารับบริการแยกเพศ ชาย,หญิง,รวม จำแนกตามสิทธิบัตร โดยแสดงสิทธิบัตรออกมาจนครบ ตั้งแต่สุดสัปดาห์ที่ผ่านมาแล้ว แต่ก็มีเหตุให้ต้องเลื่อนเนื่องจากวันเสาร์ - อาทิตย์ที่ผ่านมามีภารกิจที่ต้องทำ (อย่างยิ่งยวด) โดยในวันเสาร์ที่โรงเรียนของลูกสาวมีการจัดแข่งขันกีฬาสี ก็ต้องพาเด็กๆ ไปร่วมงานตั้งแต่เช้า กว่าจะกลับมาถึงบ้านได้ก็บ่ายแก่ๆ อากาศร้อนอบอ้าวมากทั้งๆ ที่เป็นฤดูฝน (แล้วจัดทำไมล่ะ ก็แปลกดี ปกติแล้วกีฬาสีเนี่ยเค้าจัดกันตอนเทอมสองกันทั้งน้าน นี่ยังไม่ปิดเทอมแรกเลย ) เหนื่อยทั้งผู้ปกครองทั้งนักเรียน ทั้งครู กลับมาก็นอนพักกันทั้งบ้าน นอนพักกันจนเย็น เย็นมากจนขี้เกียจไปซะ วันอาทิตย์ก็ต้องไปประชุมเกี่ยวกับพฤติกรรมการบริการ ที่ทางทีมงานพัฒนาทรัพยากรมนุษย์เค้าจัดขึ้นอีก พอกลับมาก็ไฟดับยาวไปถึงตอนดึก ช่วงนี้ไฟดับบ่อยมากทั้งๆ ที่บ้านก็อยู่ใกล้สำนักงานไฟฟ้านะ (เกียวกันด้วยเร๊อะ) เลยเถิดมาถึงวันนี้จนได้&lt;br&gt;&lt;br /&gt;เอาล่ะ เฉลยเลยแล้วกัน ตอนแรกเราก็นับเฉพาะเพศชายก่อนโดย (สีแดงคือสิ่งที่เพิ่มเข้าไป) ตั้งชื่อไว้ก่อนว่า temp1&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number AS contract_plans_number&lt;br /&gt; ,COUNT(t_visit.t_visit_id) AS total&lt;br /&gt;FROM&lt;br /&gt; b_contract_plans,t_visit,t_visit_payment&lt;span style="color: rgb(255, 0, 0);"&gt;,t_patient&lt;/span&gt;&lt;br /&gt;WHERE&lt;br /&gt; t_visit.t_visit_id=t_visit_payment.t_visit_id&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;AND t_visit.visit_hn = t_patient.patient_hn&lt;/span&gt;&lt;br /&gt; AND t_visit_payment.b_contract_plans_id=b_contract_plans.b_contract_plans_id&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;AND t_patient.f_sex_id='1'&lt;/span&gt;&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time,0,11) BETWEEN '2548-07-15' and '2548-07-15')&lt;br /&gt;GROUP BY&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;เมื่อได้เพศชายแล้วก็นับเพศหญิงต่อโดยใช้ SQL ชุดเดียวกันเพียงแต่เปลี่ยน t_patient.f_sex_id จาก 1 เป็น 2 ตั้งชื่อไว้ว่า temp2&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number AS contract_plans_number&lt;br /&gt; ,COUNT(t_visit.t_visit_id) AS total&lt;br /&gt;FROM&lt;br /&gt; b_contract_plans,t_visit,t_visit_payment&lt;span style="color: rgb(255, 0, 0);"&gt;,t_patient&lt;/span&gt;&lt;br /&gt;WHERE&lt;br /&gt; t_visit.t_visit_id=t_visit_payment.t_visit_id&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;AND t_visit.visit_hn = t_patient.patient_hn&lt;/span&gt;&lt;br /&gt; AND t_visit_payment.b_contract_plans_id=b_contract_plans.b_contract_plans_id&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;AND t_patient.f_sex_id='2'&lt;/span&gt;&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time,0,11) BETWEEN '2548-07-15' and '2548-07-15')&lt;br /&gt;GROUP BY&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;แล้วก็นับทั้งหมด (รวมชายและหญิง) ตั้งชื่อเป็น temp3 ดังนี้&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number AS contract_plans_number&lt;br /&gt; ,COUNT(t_visit.t_visit_id) AS total&lt;br /&gt;FROM&lt;br /&gt; b_contract_plans,t_visit,t_visit_payment&lt;br /&gt;WHERE&lt;br /&gt; t_visit.t_visit_id=t_visit_payment.t_visit_id&lt;br /&gt; AND t_visit_payment.b_contract_plans_id=b_contract_plans.b_contract_plans_id&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time,0,11) BETWEEN '2548-07-15' and '2548-07-15')&lt;br /&gt;GROUP BY&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ทีนี้ก็นับสิทธิบัตรทั้งหมดออกมา ตั้งชื่อว่า temp4&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt;FROM&lt;br /&gt; b_contract_plans&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;เริ่มการ JOIN โดยการใช้ temp4 เป็นตัวตั้ง แล้วเอา temp1,temp2,temp3 มา JOIN ตามที่ร่างไว้อย่างนี้&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;,temp1.total AS male&lt;br /&gt; ,temp2.total AS female&lt;br /&gt; ,temp3.total AS total_all&lt;/span&gt;&lt;br /&gt;FROM&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;(&lt;/span&gt;b_contract_plans &lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;LEFT JOIN&lt;br /&gt;  (&lt;br /&gt;   SQL ชุดที่หนึ่ง&lt;br /&gt;  ) AS temp1 ON b_contract_plans.contract_plans_number=temp1.contract_plans_number&lt;br /&gt; LEFT JOIN&lt;br /&gt;  (&lt;br /&gt;   SQL ชุดที่สอง&lt;br /&gt;  ) AS temp2 ON b_contract_plans.contract_plans_number=temp2.contract_plans_number&lt;br /&gt; LEFT JOIN&lt;br /&gt;  (&lt;br /&gt;   SQL ชุดที่สาม&lt;br /&gt;  ) AS temp3 ON b_contract_plans.contract_plans_number=temp3.contract_plans_number   &lt;br /&gt; )&lt;br /&gt;GROUP BY&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt; ,male&lt;br /&gt; ,female&lt;br /&gt; ,total_all&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;เมื่อแทนค่า temp1 , temp2 , temp3 ด้วยชุดคำสั่งแล้วก็จะได้เป็นดังนี้&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt; ,temp1.total AS male&lt;br /&gt; ,temp2.total AS female&lt;br /&gt; ,temp3.total AS total_all&lt;br /&gt;FROM&lt;br /&gt; (b_contract_plans LEFT JOIN&lt;br /&gt;  (&lt;br /&gt;   SELECT&lt;br /&gt;    b_contract_plans.contract_plans_number AS contract_plans_number&lt;br /&gt;    ,COUNT(t_visit.t_visit_id) AS total&lt;br /&gt;   FROM&lt;br /&gt;    b_contract_plans,t_visit,t_visit_payment,t_patient&lt;br /&gt;   WHERE&lt;br /&gt;    t_visit.t_visit_id=t_visit_payment.t_visit_id&lt;br /&gt;    AND t_visit.visit_hn = t_patient.patient_hn&lt;br /&gt;    AND t_visit_payment.b_contract_plans_id=b_contract_plans.b_contract_plans_id&lt;br /&gt;    AND t_patient.f_sex_id='1'&lt;br /&gt;    AND t_visit.f_visit_type_id='0'&lt;br /&gt;    AND t_visit.f_visit_status_id='3'&lt;br /&gt;    AND (SUBSTRING(t_visit.visit_financial_discharge_time,0,11) BETWEEN '2548-07-15' and '2548-07-15')    &lt;br /&gt;   GROUP BY&lt;br /&gt;    b_contract_plans.contract_plans_number&lt;br /&gt;    ,b_contract_plans.contract_plans_description&lt;br /&gt;  ) AS temp1 ON b_contract_plans.contract_plans_number=temp1.contract_plans_number&lt;br /&gt;  LEFT JOIN&lt;br /&gt;  (&lt;br /&gt;   SELECT&lt;br /&gt;    b_contract_plans.contract_plans_number AS contract_plans_number&lt;br /&gt;    ,COUNT(t_visit.t_visit_id) AS total&lt;br /&gt;   FROM&lt;br /&gt;    b_contract_plans,t_visit,t_visit_payment,t_patient&lt;br /&gt;   WHERE&lt;br /&gt;    t_visit.t_visit_id=t_visit_payment.t_visit_id&lt;br /&gt;    AND t_visit.visit_hn = t_patient.patient_hn&lt;br /&gt;    AND t_visit_payment.b_contract_plans_id=b_contract_plans.b_contract_plans_id&lt;br /&gt;    AND t_patient.f_sex_id='2'&lt;br /&gt;    AND t_visit.f_visit_type_id='0'&lt;br /&gt;    AND t_visit.f_visit_status_id='3'&lt;br /&gt;    AND (SUBSTRING(t_visit.visit_financial_discharge_time,0,11) BETWEEN '2548-07-15' and '2548-07-15')&lt;br /&gt;   GROUP BY&lt;br /&gt;    b_contract_plans.contract_plans_number&lt;br /&gt;    ,b_contract_plans.contract_plans_description&lt;br /&gt;  ) AS temp2 ON b_contract_plans.contract_plans_number=temp2.contract_plans_number&lt;br /&gt;  LEFT JOIN&lt;br /&gt;  (&lt;br /&gt;   SELECT&lt;br /&gt;    b_contract_plans.contract_plans_number AS contract_plans_number&lt;br /&gt;    ,COUNT(t_visit.t_visit_id) AS total&lt;br /&gt;   FROM&lt;br /&gt;    b_contract_plans,t_visit,t_visit_payment&lt;br /&gt;   WHERE&lt;br /&gt;    t_visit.t_visit_id=t_visit_payment.t_visit_id&lt;br /&gt;    AND t_visit_payment.b_contract_plans_id=b_contract_plans.b_contract_plans_id&lt;br /&gt;    AND t_visit.f_visit_type_id='0'&lt;br /&gt;    AND t_visit.f_visit_status_id='3'&lt;br /&gt;    AND (SUBSTRING(t_visit.visit_financial_discharge_time,0,11) BETWEEN '2548-07-15' and '2548-07-15')&lt;br /&gt;   GROUP BY&lt;br /&gt;    b_contract_plans.contract_plans_number&lt;br /&gt;    ,b_contract_plans.contract_plans_description&lt;br /&gt;  ) AS temp3 ON b_contract_plans.contract_plans_number=temp3.contract_plans_number  &lt;br /&gt; )&lt;br /&gt;GROUP BY&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt; ,male&lt;br /&gt; ,female&lt;br /&gt; ,total_all&lt;br /&gt;ORDER BY&lt;br /&gt; b_contract_plans.contract_plans_number&lt;/pre&gt;&lt;br /&gt;ก็ได้ผลของการคิวรี่ดังนี้&lt;br /&gt;&lt;pre class=stress&gt;A1     ชำระเงินเอง     1     3     4&lt;br /&gt;A11     ผู้ประสบภัยจากรถ (หลักฐานครบ)               &lt;br /&gt;A12     ผู้ประสบภัยจากรถ (หลักฐานไม่ครบ)     3          3&lt;br /&gt;A21     เบิกได้ (ข้าราชการ/ลูกจ้างประจำ)     8     8     16&lt;br /&gt;A22     เบิกได้ (รัฐวิสาหกิจ,ส่วนท้องถิ่น)               &lt;br /&gt;A71     บัตรประกันสังคม (คู่สัญญา)               &lt;br /&gt;A72     บัตรประกันสังคม (คลอด ชำระเอง)               &lt;br /&gt;A73     บัตรประกันสังคม (ญาติสายตรง)               &lt;br /&gt;A74     บัตรประกันสังคม (เจ้าหน้าที่โรงพยาบาล)          1     1&lt;br /&gt;A75     บัตรประกันสังคม (ทำฟัน ชำระเอง)               &lt;br /&gt;A76     บัตรประกันสังคม (ไม่ใช่คู่สัญญา ชำระเงินเอง)     1          1&lt;br /&gt;AA     บัตรทองมี ท (เด็ก 0-5 ปี)     3          3&lt;br /&gt;AA1     บัตรทองมี ท (เด็ก 6-12 ปี)     1     2     3&lt;br /&gt;AB     บัตรทองมี ท (ผู้มีรายได้น้อย)     9     14     23&lt;br /&gt;AC     บัตรทองมี ท (นักเรียนมัธยมต้น)     2     2     4&lt;br /&gt;AD     บัตรทองมี ท (ผู้พิการ)     1          1&lt;br /&gt;AE     บัตรทองมี ท (ทหารผ่านศึก)          1     1&lt;br /&gt;AF     บัตรทองมี ท (สมณเพศ)     2          2&lt;br /&gt;AG     บัตรทองมี ท (ผู้สูงอายุ)     13     14     27&lt;br /&gt;AH     บัตรทองมี ท (บัตรชั่วคราว)               &lt;br /&gt;AH1     บัตรทองมี ท (พอสว)               &lt;br /&gt;AH2     บัตรทองมี ท (นอกเครือข่าย ชำระเงินเอง)               &lt;br /&gt;AH3     บัตรทองมี ท (นอกเครือข่ายฉุกเฉิน)     1          1&lt;br /&gt;AH4     บัตรแรงงานต่างด้าว (ในเครือข่าย)               &lt;br /&gt;AH5     บัตรแรงงานต่างด้าว (นอกเครือข่าย)               &lt;br /&gt;AH6     บัตรทองมี ท (ในเครือข่าย ชำระเงินเอง)               &lt;br /&gt;AJ     บัตรทองมี ท (ผู้นำชุมชน)     2     2     4&lt;br /&gt;AK1     บัตรทองมี ท (อสม ในเขตอำเภอ)     2     2     4&lt;br /&gt;AK2     บัตรทองมี ท (อสม นอกเขตอำเภอ)               &lt;br /&gt;AZ     สังคมสงเคราะห์               &lt;br /&gt;UC1     บัตรทองเสียค่าธรรมเนียม     12     18     30&lt;br /&gt;UC2     บัตรทองเสียค่าธรรมเนียม (นอกเครือข่าย ชำระเงินเอง)          1     1&lt;br /&gt;UC3     บัตรทองเสียค่าธรรมเนียม (นอกเครือข่ายฉุกเฉิน)               &lt;br /&gt;UC4     บัตรทองเสียค่าธรรมเนียม (ในเครือข่าย ชำระเงินเอง)&lt;/pre&gt;&lt;br /&gt;รู้สึกว่ามันเยิ่นเย้อ มากไปหน่อย ลองดูอีกวิธีดีกว่า ตัด temp2, temp3 ออกไป temp4 คงเดิม แต่ temp1 มีการโมดิฟายเล็กน้อยโดยเอา temp1, temp2, temp3 มารวมกัน อ่า รวมได้ยังงัย เทคนิคนี้เรียกว่า เทคนิคการคิวรี่แบบ Pivot Table ดูกันเล้ย&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number AS contract_plans_number&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;,SUM(CASE when t_patient.f_sex_id = '1' THEN 1 ELSE 0 END) AS male&lt;br /&gt; ,SUM(CASE when t_patient.f_sex_id = '2' THEN 1 ELSE 0 END) AS female&lt;br /&gt; ,COUNT(t_visit.t_visit_id) AS total&lt;/span&gt;&lt;br /&gt;FROM&lt;br /&gt; b_contract_plans,t_visit,t_visit_payment,t_patient&lt;br /&gt;WHERE&lt;br /&gt; t_visit.t_visit_id=t_visit_payment.t_visit_id&lt;br /&gt; AND t_visit.visit_hn = t_patient.patient_hn&lt;br /&gt; AND t_visit_payment.b_contract_plans_id=b_contract_plans.b_contract_plans_id&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time,0,11) BETWEEN '2548-07-15' and '2548-07-15')&lt;br /&gt;GROUP BY&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt;ORDER BY&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;SUM(CASE when t_patient.f_sex_id = '1' THEN 1 ELSE 0 END) AS male&lt;br&gt;&lt;br /&gt;อธิบายนิดนึงครับ ว่าตั้งแต่ CASE ........ไปจนถึง END หมายความว่า..&lt;br&gt;&lt;br /&gt;เมื่อ t_patient.f_sex_id='1' ให้มีค่าเท่ากับ 1  ส่วนค่าอื่นๆ (t_patient.f_sex_id='2') ไม่สนใจให้เป็นศูนย์ ไปจนครบเงื่อนไขตามที่เรา WHERE ไว้ เมื่อครบแล้วก็ให้ SUM ได้เท่าไรเก็บไว้ใน male ส่วนค่า female นั้นก็ให้นับคล้ายๆ กันเพียงแต่บังคับให้นับเฉพาะ t_patient.f_sex_id='2' เท่านั้นให้เป็น 1 บรรทัดสุดท้ายคือ COUNT(t_visit.t_visit_id) ก็คือนับทั้ง t_patient.f_sex_id='1' และ t_patient.f_sex_id='2' เก็บไว้ในค่า total พอได้ temp1 เช่นนี้แล้วก็เอามา JOIN กับ temp4 เหมือนเดิม ได้ดังนี้&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;,temp1.male AS male&lt;br /&gt; ,temp1.female AS female&lt;br /&gt; ,temp1.total AS total_all&lt;/span&gt;&lt;br /&gt;FROM&lt;br /&gt; (b_contract_plans LEFT JOIN&lt;br /&gt;  (&lt;br /&gt;   SELECT&lt;br /&gt;    b_contract_plans.contract_plans_number AS contract_plans_number&lt;br /&gt;    &lt;span style="color: rgb(255, 0, 0);"&gt;,SUM(CASE when t_patient.f_sex_id = '1' THEN 1 ELSE 0 END) AS male&lt;br /&gt;    ,SUM(CASE when t_patient.f_sex_id = '2' THEN 1 ELSE 0 END) AS female&lt;br /&gt;    ,COUNT(t_visit.t_visit_id) AS total&lt;/span&gt;&lt;br /&gt;   FROM&lt;br /&gt;    b_contract_plans,t_visit,t_visit_payment,t_patient&lt;br /&gt;   WHERE&lt;br /&gt;    t_visit.t_visit_id=t_visit_payment.t_visit_id&lt;br /&gt;    AND t_visit.visit_hn = t_patient.patient_hn&lt;br /&gt;    AND t_visit_payment.b_contract_plans_id=b_contract_plans.b_contract_plans_id&lt;br /&gt;    AND t_visit.f_visit_type_id='0'&lt;br /&gt;    AND t_visit.f_visit_status_id='3'&lt;br /&gt;    AND (SUBSTRING(t_visit.visit_financial_discharge_time,0,11) BETWEEN '2548-07-15' and '2548-07-15')&lt;br /&gt;   GROUP BY&lt;br /&gt;    b_contract_plans.contract_plans_number&lt;br /&gt;    ,b_contract_plans.contract_plans_description&lt;br /&gt;   ORDER BY&lt;br /&gt;    b_contract_plans.contract_plans_number&lt;br /&gt;  ) AS temp1 ON b_contract_plans.contract_plans_number=temp1.contract_plans_number&lt;br /&gt; )&lt;br /&gt;GROUP BY&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt; ,male&lt;br /&gt; ,female&lt;br /&gt; ,total_all&lt;br /&gt;ORDER BY&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt;&lt;/pre&gt;พอลองรันดูก็ได้ผลดังนี้&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;A1     ชำระเงินเอง     1     3     4&lt;br /&gt;A11     ผู้ประสบภัยจากรถ (หลักฐานครบ)               &lt;br /&gt;A12     ผู้ประสบภัยจากรถ (หลักฐานไม่ครบ)     3          3&lt;br /&gt;A21     เบิกได้ (ข้าราชการ/ลูกจ้างประจำ)     8     8     16&lt;br /&gt;A22     เบิกได้ (รัฐวิสาหกิจ,ส่วนท้องถิ่น)               &lt;br /&gt;A71     บัตรประกันสังคม (คู่สัญญา)               &lt;br /&gt;A72     บัตรประกันสังคม (คลอด ชำระเอง)               &lt;br /&gt;A73     บัตรประกันสังคม (ญาติสายตรง)               &lt;br /&gt;A74     บัตรประกันสังคม (เจ้าหน้าที่โรงพยาบาล)          1     1&lt;br /&gt;A75     บัตรประกันสังคม (ทำฟัน ชำระเอง)               &lt;br /&gt;A76     บัตรประกันสังคม (ไม่ใช่คู่สัญญา ชำระเงินเอง)     1          1&lt;br /&gt;AA     บัตรทองมี ท (เด็ก 0-5 ปี)     3          3&lt;br /&gt;AA1     บัตรทองมี ท (เด็ก 6-12 ปี)     1     2     3&lt;br /&gt;AB     บัตรทองมี ท (ผู้มีรายได้น้อย)     9     14     23&lt;br /&gt;AC     บัตรทองมี ท (นักเรียนมัธยมต้น)     2     2     4&lt;br /&gt;AD     บัตรทองมี ท (ผู้พิการ)     1          1&lt;br /&gt;AE     บัตรทองมี ท (ทหารผ่านศึก)          1     1&lt;br /&gt;AF     บัตรทองมี ท (สมณเพศ)     2          2&lt;br /&gt;AG     บัตรทองมี ท (ผู้สูงอายุ)     13     14     27&lt;br /&gt;AH     บัตรทองมี ท (บัตรชั่วคราว)               &lt;br /&gt;AH1     บัตรทองมี ท (พอสว)               &lt;br /&gt;AH2     บัตรทองมี ท (นอกเครือข่าย ชำระเงินเอง)               &lt;br /&gt;AH3     บัตรทองมี ท (นอกเครือข่ายฉุกเฉิน)     1          1&lt;br /&gt;AH4     บัตรแรงงานต่างด้าว (ในเครือข่าย)               &lt;br /&gt;AH5     บัตรแรงงานต่างด้าว (นอกเครือข่าย)               &lt;br /&gt;AH6     บัตรทองมี ท (ในเครือข่าย ชำระเงินเอง)               &lt;br /&gt;AJ     บัตรทองมี ท (ผู้นำชุมชน)     2     2     4&lt;br /&gt;AK1     บัตรทองมี ท (อสม ในเขตอำเภอ)     2     2     4&lt;br /&gt;AK2     บัตรทองมี ท (อสม นอกเขตอำเภอ)               &lt;br /&gt;AZ     สังคมสงเคราะห์               &lt;br /&gt;UC1     บัตรทองเสียค่าธรรมเนียม     12     18     30&lt;br /&gt;UC2     บัตรทองเสียค่าธรรมเนียม (นอกเครือข่าย ชำระเงินเอง)          1     1&lt;br /&gt;UC3     บัตรทองเสียค่าธรรมเนียม (นอกเครือข่ายฉุกเฉิน)               &lt;br /&gt;UC4     บัตรทองเสียค่าธรรมเนียม (ในเครือข่าย ชำระเงินเอง)&lt;/pre&gt;&lt;br /&gt;ตัดออกไปได้หลายบรรทัดเลยล่ะ ดูโค๊ด SQL ก็ง่ายกว่า อิ อิ ตอนแรกว่าจะไม่เอามาพูดแล้วนะ กลัวมันจะยาวไปจนเอียน แต่ทนไม่ได้ต้องเอามาพูดให้รู้แจ้งเห็นจริง เหมือนที่เรามีประสบการณ์เคยทำมา จะได้รู้สึกว่ามัน เข้าถึงจริงๆ มีความรู้สึกว่าถ้าไม่ได้พูดเสียเดี๋ยวนี้มันอึดอัดกับความรู้สึก ไม่ใช่ว่าสักแต่พูด แต่พูดต้องพูดให้หมด ไม่มีกั๊กไว้ คนที่เข้ามาอ่านจะได้อะไรกลับไปมากๆ หน่อย สมกับที่เสียเวลาเข้ามาอ่านตั้งนาน จะได้เอาไปประยุกต์ใช้ได้ให้เหมาะกับงาน เราเองก็ไม่ต้องอึดอัด สรุปแล้วก็ Happy กัน จบล่ะนะ&lt;br /&gt;&lt;br&gt;&lt;br&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;แหล่งความรู้และอ้างอิง&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;John C. Worsley and Joshua D. Drake, Practical PostgreSQL&lt;br&gt;&lt;br /&gt; O'Reilly &amp; Associates, Inc., CA ,USA &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112663007413202991?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112663007413202991/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112663007413202991' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112663007413202991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112663007413202991'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/09/sql-4.html' title='เรื่องของ SQL ตอนที่ 4'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112575991738505510</id><published>2005-09-03T22:00:00.000+07:00</published><updated>2005-09-25T21:02:12.286+07:00</updated><title type='text'>เรื่องของ SQL ตอนที่ 3</title><content type='html'>ท้ายๆของตอนที่ 2 ได้เกริ่นไว้ว่าจะมาพูดต่อเรื่องของน้องจอย (JOIN) กว่าจะได้เริ่มก็ล่วงเลยมาจนถึงวันนี้ เนื่องจากมัวไปทำบล็อกอยู่ที่ &lt;a href=http://iamuthai.blogspot.com&gt;blogger dot com&lt;/a&gt; ซะนานจนถึงเมื่อคืนก็ลงตัวจนได้ ความจริงถ้าผมไม่เรื่องมากก็เสร็จไปนานแล้วล่ะ คือเรื่องราวมีอยู่ว่าไม่ค่อยชอบใจ template ที่ blogger ให้มาสักเท่าไหร่ก็เลยไปหาที่ถูกใจเอาใหม่ที่ &lt;a href=http://blogger-templates.blogspot.com/&gt;blogger-templates dot com&lt;/a&gt; แต่ก็ต้องมานั่งแก้ไข CSS (Cascade Style Sheet) อยู่นาน ความที่เป็นเรื่องที่ยังไม่ได้เรียนรู้ กว่าจะเข้าใจอะไรสักอย่างก็ต้องทุ่มทุนสร้างยอมนั่งแกะโค๊ดของ CSS เปิดเน็ตไปด้วยค้นหาข้อมูลไปด้วย กว่าจะพอใจก็ตีหนึ่งเข้าไปแล้ว แถมไม่พอตอนเช้าวันนี้ก็ต้องไปประชุมผู้ปกครองที่โรงเรียนอัยยสิริ (โรงเรียนที่ลูกสาวของผมเรียนอยู่) อีกครึ่งค่อนวันกลับมาว่าจะลุยต่อ ฝนเจ้ากรรมดันตกลงมาหนัก ทำเอาไฟดับไปทั้งเมือง ปาเข้าไปตั้งสามโมงกว่าถึงจะมาได้&lt;br&gt;&lt;br /&gt;เพื่อไม่ให้เป็นการเสียเวลา เริ่มกันเลย&lt;br&gt;&lt;br /&gt;การ JOIN เนี่ยปกติแล้วเค้าใช้ทำกับตารางนะครับ ไม่ใช่ทำกับดาต้าเบส ประมาณว่าเอาตารางตั้งแต่สองตารางมาเชื่อมโยงกัน โดยอาศัยคีย์หลักอันใดอันหนึ่ง ซึ่งก็หมายความว่าทั้งสองตารางนั้นอย่างน้อยที่สุดต้องมีฟิลด์ใดฟิลด์หนึ่งเหมือนกัน ตารางนี่อาจเป็นได้ทั้งตารางที่มีอยู่จริง หรือจะเป็นตารางที่ได้จากการคิวรี่ออกมาจาก SQL ก็ได้นะครับ&lt;br&gt;&lt;br /&gt;ยกตัวอย่างดีกว่า จะได้เห็นภาพกันชัดๆ เกิดว่าผู้บริหารอยากทราบว่าวันนี้มีผู้ป่วยมารับบริการกี่คน จำแนกตามสิทธิบัตร ? ก็เขียนเป็น SQL ได้ดังนี้ สมมติอีกแล้วว่าให้เป็นชุดที่หนึ่ง&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt; ,COUNT(t_visit.t_visit_id) AS total&lt;br /&gt;FROM&lt;br /&gt; b_contract_plans,t_visit,t_visit_payment&lt;br /&gt;WHERE&lt;br /&gt; t_visit.t_visit_id=t_visit_payment.t_visit_id&lt;br /&gt; AND t_visit_payment.b_contract_plans_id=b_contract_plans.b_contract_plans_id&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time,0,11) BETWEEN '2548-07-01' and '2548-07-01')&lt;br /&gt;GROUP BY&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt;&lt;/pre&gt;ก็ได้ผลลัพท์ดังนี้&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;AC    บัตรทองมี ท (นักเรียนมัธยมต้น)    1&lt;br /&gt;AG    บัตรทองมี ท (ผู้สูงอายุ)    20&lt;br /&gt;A11    ผู้ประสบภัยจากรถ (หลักฐานครบ)    1&lt;br /&gt;A71    บัตรประกันสังคม (คู่สัญญา)    1&lt;br /&gt;AJ    บัตรทองมี ท (ผู้นำชุมชน)    1&lt;br /&gt;UC1    บัตรทองเสียค่าธรรมเนียม    32&lt;br /&gt;AA    บัตรทองมี ท (เด็ก 0-5 ปี)    12&lt;br /&gt;A76    บัตรประกันสังคม (ไม่ใช่คู่สัญญา ชำระเงินเอง)    1&lt;br /&gt;A21    เบิกได้ (ข้าราชการ/ลูกจ้างประจำ)    12&lt;br /&gt;UC2    บัตรทองเสียค่าธรรมเนียม (นอกเครือข่าย ชำระเงินเอง)    1&lt;br /&gt;AB    บัตรทองมี ท (ผู้มีรายได้น้อย)    45&lt;br /&gt;AK2    บัตรทองมี ท (อสม นอกเขตอำเภอ)    2&lt;br /&gt;AF    บัตรทองมี ท (สมณเพศ)    1&lt;br /&gt;A1    ชำระเงินเอง    1&lt;br /&gt;AK1    บัตรทองมี ท (อสม ในเขตอำเภอ)    7&lt;br /&gt;AA1    บัตรทองมี ท (เด็ก 6-12 ปี)    12&lt;br /&gt;&lt;/pre&gt;ถุกต้องตามตำราเป๊ะ ไม่มีอะไรที่ผิดพลาดอีกแล้ว สังเกตุนิดนึงนะว่าสิทธิบัตรที่เรามีอยู่จริงน่ะมันมีเยอะกว่านี้มาก แต่ทำไมผลการคิวรี่ที่ได้มาน่ะ สิทธิบัตรทำไมออกมาไม่ครบ ถ้าผู้บริหารไม่ซีเรียส ก็ไม่มีอะไรทำต่อแล้ว แต่ถ้า....... เราก็ต้องทำให้สิทธิบัตรน่ะแสดงออกมาจนครบถึงแม้ว่าผลการนับจำนวนจะเป็นศูนย์ก็ตาม อืมอาจมีวิธีทำได้อย่างน้อยคือวิธีที่จะนำเสนอดังต่อไปนี้&lt;br&gt;&lt;br /&gt;&lt;stress1&gt;Concept&lt;/stress&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;การจะทำให้สิทธิบัตรแสดงออกมาหมดเนี่ยมันไม่ยากหรอกเราก็ &lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt;FROM&lt;br /&gt; b_contract_plans&lt;/pre&gt;&lt;br /&gt;ผลลัพท์ก็ได้ออกมาเป็นอย่างนี้&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;A1    ชำระเงินเอง&lt;br /&gt;A72    บัตรประกันสังคม (คลอด ชำระเอง)&lt;br /&gt;A76    บัตรประกันสังคม (ไม่ใช่คู่สัญญา ชำระเงินเอง)&lt;br /&gt;AH2    บัตรทองมี ท (นอกเครือข่าย ชำระเงินเอง)&lt;br /&gt;AH5    บัตรแรงงานต่างด้าว (นอกเครือข่าย)&lt;br /&gt;AH6    บัตรทองมี ท (ในเครือข่าย ชำระเงินเอง)&lt;br /&gt;UC2    บัตรทองเสียค่าธรรมเนียม (นอกเครือข่าย ชำระเงินเอง)&lt;br /&gt;UC4    บัตรทองเสียค่าธรรมเนียม (ในเครือข่าย ชำระเงินเอง)&lt;br /&gt;A21    เบิกได้ (ข้าราชการ/ลูกจ้างประจำ)&lt;br /&gt;A22    เบิกได้ (รัฐวิสาหกิจ,ส่วนท้องถิ่น)&lt;br /&gt;A73    บัตรประกันสังคม (ญาติสายตรง)&lt;br /&gt;A74    บัตรประกันสังคม (เจ้าหน้าที่โรงพยาบาล)&lt;br /&gt;AK1    บัตรทองมี ท (อสม ในเขตอำเภอ)&lt;br /&gt;A71    บัตรประกันสังคม (คู่สัญญา)&lt;br /&gt;AA    บัตรทองมี ท (เด็ก 0-5 ปี)&lt;br /&gt;AB    บัตรทองมี ท (ผู้มีรายได้น้อย)&lt;br /&gt;AC    บัตรทองมี ท (นักเรียนมัธยมต้น)&lt;br /&gt;AE    บัตรทองมี ท (ทหารผ่านศึก)&lt;br /&gt;AD    บัตรทองมี ท (ผู้พิการ)&lt;br /&gt;AG    บัตรทองมี ท (ผู้สูงอายุ)&lt;br /&gt;AH    บัตรทองมี ท (บัตรชั่วคราว)&lt;br /&gt;AH1    บัตรทองมี ท (พอสว)&lt;br /&gt;AH3    บัตรทองมี ท (นอกเครือข่ายฉุกเฉิน)&lt;br /&gt;AH4    บัตรแรงงานต่างด้าว (ในเครือข่าย)&lt;br /&gt;AJ    บัตรทองมี ท (ผู้นำชุมชน)&lt;br /&gt;AK2    บัตรทองมี ท (อสม นอกเขตอำเภอ)&lt;br /&gt;UC1    บัตรทองเสียค่าธรรมเนียม&lt;br /&gt;UC3    บัตรทองเสียค่าธรรมเนียม (นอกเครือข่ายฉุกเฉิน)&lt;br /&gt;AF    บัตรทองมี ท (สมณเพศ)&lt;br /&gt;AZ    สังคมสงเคราะห์&lt;br /&gt;A75    บัตรประกันสังคม (ทำฟัน ชำระเอง)&lt;br /&gt;AA1    บัตรทองมี ท (เด็ก 6-12 ปี)&lt;br /&gt;A11    ผู้ประสบภัยจากรถ (หลักฐานครบ)&lt;br /&gt;A12    ผู้ประสบภัยจากรถ (หลักฐานไม่ครบ)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ซะก็สิ้นเรื่อง สมมติให้ SQL นี้เป็นชุดที่สอง&lt;/li&gt;&lt;br /&gt; &lt;li&gt;ก็ได้สองตารางตามที่เกริ่นให้ฟังมาแล้วคือ ตารางที่ได้จากการคิวรี่จาก SQL ชุดที่หนึ่ง และตารางที่ได้จากการคิวรี่จาก SQL ชุดที่สอง อ๊ะๆ เริ่มเข้าเค้าแล้วล่ะนะ ทีนี้เราก็เอาตารางสองตารางนี้มา JOIN กันโดยอาศัย สิ่งสองตารางนี้มีเหมือนกันคือ b_contract_plans.contract_plans_number แล้วจะเริ่มยังงัยดีล่ะ โจทย์ของเราก็คือต้องการแสดงสิทธิบัตรทั้งหมดออกมา ก็น่าจะใช้ SQL ชุดที่สองมาก่อน แล้วเอาชุดที่หนึ่งมา JOIN โดยใช้ b_contract_plans.contract_plans_number เป็นพ่อสื่อพ่อชักให้&lt;/li&gt;&lt;br /&gt; &lt;li&gt;การ JOIN ตารางนั้นมีหลายรูปแบบ หลายท่านอาจจะไม่ทราบว่า SQL ที่คิวรี่ข้อมูลจากหลายตารางนั้นน่ะมีการ join กันอยู่แล้วดูจากตรง WHERE เช่น&lt;br&gt;&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;WHERE&lt;br /&gt; t_visit.t_visit_id=t_visit_payment.t_visit_id&lt;br /&gt; AND t_visit_payment.b_contract_plans_id=b_contract_plans.b_contract_plans_id&lt;/pre&gt;จาก SQL ชุดที่หนึ่ง อันนีี้ก็เรียกว่า JOIN เหมือนกันแต่เป็นการ JOIN แบบธรรมดาที่สุด (INNER JOIN) แต่สิ่งที่เราจะทำกันต่อไปนี้เรียกว่า LEFT JOIN คือเอาตารางแรก ที่อยู่ทางซ้ายเป็นหลัก แล้วเอาตารางที่สองมา JOIN เราลองมาร่างดูคร่าวๆ ก่อนแล้วกัน&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt;FROM&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;(&lt;/span&gt;b_contract_plans &lt;span style="color: rgb(255, 0, 0);"&gt;LEFT JOIN&lt;br /&gt; (&lt;br /&gt; SQL ชุดที่หนึ่ง &lt;br /&gt;  ) AS temp1(ชื่อที่เราสมมติขึ้นมา)  ON b_contract_plans.contract_plans_number = temp1.contract_plans_number )&lt;/span&gt;&lt;/pre&gt;ได้ผลลัพท์ดังนี้&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;A1    ชำระเงินเอง&lt;br /&gt;A72    บัตรประกันสังคม (คลอด ชำระเอง)&lt;br /&gt;A76    บัตรประกันสังคม (ไม่ใช่คู่สัญญา ชำระเงินเอง)&lt;br /&gt;AH2    บัตรทองมี ท (นอกเครือข่าย ชำระเงินเอง)&lt;br /&gt;AH5    บัตรแรงงานต่างด้าว (นอกเครือข่าย)&lt;br /&gt;AH6    บัตรทองมี ท (ในเครือข่าย ชำระเงินเอง)&lt;br /&gt;UC2    บัตรทองเสียค่าธรรมเนียม (นอกเครือข่าย ชำระเงินเอง)&lt;br /&gt;UC4    บัตรทองเสียค่าธรรมเนียม (ในเครือข่าย ชำระเงินเอง)&lt;br /&gt;A21    เบิกได้ (ข้าราชการ/ลูกจ้างประจำ)&lt;br /&gt;A22    เบิกได้ (รัฐวิสาหกิจ,ส่วนท้องถิ่น)&lt;br /&gt;A73    บัตรประกันสังคม (ญาติสายตรง)&lt;br /&gt;A74    บัตรประกันสังคม (เจ้าหน้าที่โรงพยาบาล)&lt;br /&gt;AK1    บัตรทองมี ท (อสม ในเขตอำเภอ)&lt;br /&gt;A71    บัตรประกันสังคม (คู่สัญญา)&lt;br /&gt;AA    บัตรทองมี ท (เด็ก 0-5 ปี)&lt;br /&gt;AB    บัตรทองมี ท (ผู้มีรายได้น้อย)&lt;br /&gt;AC    บัตรทองมี ท (นักเรียนมัธยมต้น)&lt;br /&gt;AE    บัตรทองมี ท (ทหารผ่านศึก)&lt;br /&gt;AD    บัตรทองมี ท (ผู้พิการ)&lt;br /&gt;AG    บัตรทองมี ท (ผู้สูงอายุ)&lt;br /&gt;AH    บัตรทองมี ท (บัตรชั่วคราว)&lt;br /&gt;AH1    บัตรทองมี ท (พอสว)&lt;br /&gt;AH3    บัตรทองมี ท (นอกเครือข่ายฉุกเฉิน)&lt;br /&gt;AH4    บัตรแรงงานต่างด้าว (ในเครือข่าย)&lt;br /&gt;AJ    บัตรทองมี ท (ผู้นำชุมชน)&lt;br /&gt;AK2    บัตรทองมี ท (อสม นอกเขตอำเภอ)&lt;br /&gt;UC1    บัตรทองเสียค่าธรรมเนียม&lt;br /&gt;UC3    บัตรทองเสียค่าธรรมเนียม (นอกเครือข่ายฉุกเฉิน)&lt;br /&gt;AF    บัตรทองมี ท (สมณเพศ)&lt;br /&gt;AZ    สังคมสงเคราะห์&lt;br /&gt;A75    บัตรประกันสังคม (ทำฟัน ชำระเอง)&lt;br /&gt;AA1    บัตรทองมี ท (เด็ก 6-12 ปี)&lt;br /&gt;A11    ผู้ประสบภัยจากรถ (หลักฐานครบ)&lt;br /&gt;A12    ผู้ประสบภัยจากรถ (หลักฐานไม่ครบ)&lt;/pre&gt;โฮ่ เกิดอะไรขึ้นกลับไปดู SQL ที่เราร่างๆไว้ก็ถึงอ้อ คือว่าเรายังไม่ได้กำหนดให้มีการแสดงผลของการนับจาก SQL ชุดที่สองคือชุดที่เราสมมติให้ชื่อ temp1 นั่นเองรู้อย่างนี้แล้วเราก็เพิ่่ม ไปอย่างนี้ (ตามอักษรสีแดง)&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; b_contract_plans.contract_plans_number&lt;br /&gt; ,b_contract_plans.contract_plans_description&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;,temp1.total AS total&lt;/span&gt;&lt;br /&gt;FROM&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;(&lt;/span&gt;b_contract_plans &lt;span style="color: rgb(255, 0, 0);"&gt;LEFT JOIN&lt;br /&gt;  (&lt;br /&gt;   SELECT&lt;br /&gt;    b_contract_plans.contract_plans_number AS contract_plans_number&lt;br /&gt;    ,b_contract_plans.contract_plans_description AS contract_plans_description&lt;br /&gt;    ,COUNT(t_visit.t_visit_id) AS total&lt;br /&gt;   FROM&lt;br /&gt;    b_contract_plans,t_visit,t_visit_payment&lt;br /&gt;   WHERE&lt;br /&gt;    t_visit.t_visit_id=t_visit_payment.t_visit_id&lt;br /&gt;    AND t_visit_payment.b_contract_plans_id=b_contract_plans.b_contract_plans_id&lt;br /&gt;    AND t_visit.f_visit_type_id='0'&lt;br /&gt;    AND t_visit.f_visit_status_id='3'&lt;br /&gt;    AND (SUBSTRING(t_visit.visit_financial_discharge_time,0,11) BETWEEN '2548-07-01' and '2548-07-01')&lt;br /&gt;   GROUP BY&lt;br /&gt;    b_contract_plans.contract_plans_number&lt;br /&gt;    ,b_contract_plans.contract_plans_description) AS temp1 ON b_contract_plans.contract_plans_number=temp1.contract_plans_number)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;ก็ได้ผลลัพท์จากการคิวรี่ดังนี้&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;A1    ชำระเงินเอง    1&lt;br /&gt;A11    ผู้ประสบภัยจากรถ (หลักฐานครบ)    1&lt;br /&gt;A12    ผู้ประสบภัยจากรถ (หลักฐานไม่ครบ)    &lt;br /&gt;A21    เบิกได้ (ข้าราชการ/ลูกจ้างประจำ)    12&lt;br /&gt;A22    เบิกได้ (รัฐวิสาหกิจ,ส่วนท้องถิ่น)    &lt;br /&gt;A71    บัตรประกันสังคม (คู่สัญญา)    1&lt;br /&gt;A72    บัตรประกันสังคม (คลอด ชำระเอง)    &lt;br /&gt;A73    บัตรประกันสังคม (ญาติสายตรง)    &lt;br /&gt;A74    บัตรประกันสังคม (เจ้าหน้าที่โรงพยาบาล)    &lt;br /&gt;A75    บัตรประกันสังคม (ทำฟัน ชำระเอง)    &lt;br /&gt;A76    บัตรประกันสังคม (ไม่ใช่คู่สัญญา ชำระเงินเอง)    1&lt;br /&gt;AA    บัตรทองมี ท (เด็ก 0-5 ปี)    12&lt;br /&gt;AA1    บัตรทองมี ท (เด็ก 6-12 ปี)    12&lt;br /&gt;AB    บัตรทองมี ท (ผู้มีรายได้น้อย)    45&lt;br /&gt;AC    บัตรทองมี ท (นักเรียนมัธยมต้น)    1&lt;br /&gt;AD    บัตรทองมี ท (ผู้พิการ)    &lt;br /&gt;AE    บัตรทองมี ท (ทหารผ่านศึก)    &lt;br /&gt;AF    บัตรทองมี ท (สมณเพศ)    1&lt;br /&gt;AG    บัตรทองมี ท (ผู้สูงอายุ)    20&lt;br /&gt;AH    บัตรทองมี ท (บัตรชั่วคราว)    &lt;br /&gt;AH1    บัตรทองมี ท (พอสว)    &lt;br /&gt;AH2    บัตรทองมี ท (นอกเครือข่าย ชำระเงินเอง)    &lt;br /&gt;AH3    บัตรทองมี ท (นอกเครือข่ายฉุกเฉิน)    &lt;br /&gt;AH4    บัตรแรงงานต่างด้าว (ในเครือข่าย)    &lt;br /&gt;AH5    บัตรแรงงานต่างด้าว (นอกเครือข่าย)    &lt;br /&gt;AH6    บัตรทองมี ท (ในเครือข่าย ชำระเงินเอง)    &lt;br /&gt;AJ    บัตรทองมี ท (ผู้นำชุมชน)    1&lt;br /&gt;AK1    บัตรทองมี ท (อสม ในเขตอำเภอ)    7&lt;br /&gt;AK2    บัตรทองมี ท (อสม นอกเขตอำเภอ)    2&lt;br /&gt;AZ    สังคมสงเคราะห์    &lt;br /&gt;UC1    บัตรทองเสียค่าธรรมเนียม    32&lt;br /&gt;UC2    บัตรทองเสียค่าธรรมเนียม (นอกเครือข่าย ชำระเงินเอง)    1&lt;br /&gt;UC3    บัตรทองเสียค่าธรรมเนียม (นอกเครือข่ายฉุกเฉิน)    &lt;br /&gt;UC4    บัตรทองเสียค่าธรรมเนียม (ในเครือข่าย ชำระเงินเอง)&lt;/pre&gt;    &lt;br /&gt; &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;คงพอจะมองเห็นภาพ LEFT JOIN กันคร่าวๆ ไปบ้างแล้วนะครับ เมื่อ LEFT JOIN สองตารางได้ ก็น่าจะ JOIN 3,4 .... ไปได้เรื่อยๆ ถ้าเราจับหลักตรงนี้ได้ ;-) จะสักร้อยก็คงไม่มีปัญหาอะไร จริงไหม &lt;span style="color: rgb(255, 0, 0);"&gt;เอางี้ดีกว่าผมมีโจทย์อยากให้ลองคิดกันเล่นๆ ว่าถ้าอยากจะทราบว่าในวันที่ 15 กรกฏาคม 2548 มีผู้ป่วยนอกมารับบริการแยกเพศ ชาย,หญิง,รวม จำแนกตามสิทธิบัตร(เอาสิทธิบัตรออกมาให้หมดนะ)&lt;/span&gt; อาจจะ comment ในบล็อกเลยก็ได้ หรือจะส่ง SQL มาให้ผมทางเมล์ หรือจะไปโพสต์ที่เวบ ในส่วนของ &lt;a href=http://www.hospital-os.com/th/modules.php?name=Forums&amp;file=viewforum&amp;f=5&gt;เรื่องการออกรายงาน&lt;/a&gt; ก็ได้ ลองคิดกันดูนะครับ ผมแนะให้นิดนึงก่อน ว่ามีตาราง t_patient เพิ่มเข้ามาอีก 1 ตาราง&lt;br /&gt;&lt;br&gt;&lt;br&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;แหล่งความรู้และอ้างอิง&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;John C. Worsley and Joshua D. Drake, Practical PostgreSQL&lt;br&gt;&lt;br /&gt; O'Reilly &amp; Associates, Inc., CA ,USA &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112575991738505510?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112575991738505510/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112575991738505510' title='1 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112575991738505510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112575991738505510'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/09/sql-3.html' title='เรื่องของ SQL ตอนที่ 3'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112564276629897445</id><published>2005-09-03T00:07:00.000+07:00</published><updated>2005-09-25T20:57:55.183+07:00</updated><title type='text'>บล็อกแรก</title><content type='html'>กว่าจะได้มาเป็นบล็อกอย่างที่ท่านเห็นนี้ก็ค่อนข้างลำบากมากมายอยู่พอควร เนื่องจากไม่ค่อยชอบใจ เทมเพลตที่ blogger ให้มาก็เลยไปหาเอาใหม่ที่ &lt;a href="http://blogger-templates.blogspot.com/"&gt;Blogger-template&lt;/a&gt; แล้วก็ต้องมานั่ง Edit CSS เอาเอง กว่าจะพอใจ แต่บล็อกที่ท่านกำลังอ่านอยู่นี้ไม่ใช่ของจริงที่ผมเคยเขียนไว้นะครับ เนื่องจากต้องมา Edit ใหม่เพื่อให้ตัวรับ Feed รับได้ คือแก้ Encoding จาก win-874 --&gt; UTF-8 OK ครับ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112564276629897445?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112564276629897445/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112564276629897445' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112564276629897445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112564276629897445'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/09/blog-post.html' title='บล็อกแรก'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112573950863514654</id><published>2005-08-30T16:17:00.000+07:00</published><updated>2005-09-25T20:48:51.840+07:00</updated><title type='text'>เรื่องของ SQL ตอนที่ 1 เพิ่มเติมอีกหน่อยนึง</title><content type='html'>ได้รับ Requirement กลับมาเกี่ยวกับ  &lt;a href=sql_episode1.html&gt;SQL ตอนที่ 1&lt;/a&gt; ว่าถ้าหากต้องการดึงเอาวันที่มารับบริการ และอายุออกมาด้วยล่ะ จะทำได้อย่างไร ก็พยายามไปค้นคว้ามารับใช้ให้จนได้แม้ว่าจะหินโคตรๆ&lt;br&gt;&lt;br /&gt;ขอย้อนกลับไปที่ SQL ชุดนั้นอีกครั้งแล้วกันเผื่อคนที่พึ่งเข้ามาอ่านครั้งแรกจะได้ปะติดปะต่อเรื่องราวได้&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt;&lt;br /&gt; t_patient.patient_hn AS hn&lt;br /&gt;&lt;br /&gt; ,pat_address.patient_name AS name&lt;br /&gt;&lt;br /&gt; ,pat_address.address AS address&lt;br /&gt;&lt;br /&gt; ,t_patient.patient_pid AS pid&lt;br /&gt;&lt;br /&gt;FROM&lt;br /&gt;&lt;br /&gt; t_patient,pat_address,t_visit,t_diag_icd10&lt;br /&gt;&lt;br /&gt;WHERE&lt;br /&gt;&lt;br /&gt; t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt;&lt;br /&gt; AND t_patient.patient_hn = pat_address.patient_hn&lt;br /&gt;&lt;br /&gt; AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt;&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt;&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt;&lt;br /&gt; AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-01-01' and '2548-03-31')          &lt;br /&gt;&lt;br /&gt; AND t_patient.patient_hn NOT IN&lt;br /&gt;&lt;br /&gt;   ( /* เริ่มต้น */&lt;br /&gt;   SELECT&lt;br /&gt;&lt;br /&gt;    DISTINCT(t_patient.patient_hn)&lt;br /&gt;&lt;br /&gt;   FROM&lt;br /&gt;&lt;br /&gt;    t_patient&lt;br /&gt;&lt;br /&gt;    ,t_visit&lt;br /&gt;&lt;br /&gt;    ,t_diag_icd10&lt;br /&gt;&lt;br /&gt;   WHERE&lt;br /&gt;&lt;br /&gt;    t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt;&lt;br /&gt;    AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt;&lt;br /&gt;    AND t_visit.f_visit_type_id='0'&lt;br /&gt;&lt;br /&gt;    AND t_visit.f_visit_status_id='3'&lt;br /&gt;&lt;br /&gt;    AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;&lt;br /&gt;      OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;&lt;br /&gt;      OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;&lt;br /&gt;      OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;br /&gt;&lt;br /&gt;    AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-01-01' and '2548-02-28')&lt;br /&gt;&lt;br /&gt;   ) /* สิ้นสุด */&lt;br /&gt;&lt;br /&gt;GROUP BY&lt;br /&gt;&lt;br /&gt; hn&lt;br /&gt;&lt;br /&gt; ,pat_address.patient_name&lt;br /&gt;&lt;br /&gt; ,pat_address.address&lt;br /&gt;&lt;br /&gt; ,t_patient.patient_pid&lt;br /&gt;&lt;br /&gt;ORDER BY hn&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;อยากได้วันที่ที่มารับบริการก็เพิ่มเข้าไปได้ครับ เอาเป็นก่อนหน้า HN ดีไหม&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;เพิ่ม SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) AS date_visit&lt;/li&gt;&lt;br /&gt; &lt;li&gt;เพิ่มอายุเข้าไปอีก อายุเนี่ยจะเอาอายุยังงัยล่ะ เอาอายุตอนไหน เอาอายุ ณ วันนี้เหรอ หรือว่าเป็นอายุตอนที่เข้ารับบริการ&lt;br /&gt;  &lt;ol&gt;&lt;br /&gt;   &lt;li&gt;ถ้าเป็นอายุ ณ วันปัจจุบัน ก็เอาวันที่ปัจจุบันตั้ง เอาวันเกิดของผู้ป่วยมาลบออก ก็เป๊ะ&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;ถ้าเป็นอายุ ตอนที่มารับบริการ ก็เอาวันที่จำหน่ายทางการเงินตั้ง เอาวันเกิดผู้ป่วยมาลบออก แต่คิดว่าคอนเซ็ปต์นี้น่าจะเวอร์คกว่า ไอเดียนี่ไม่ยาก แต่จะทำอย่างไรล่ะทีนี้ ที่ว่ายากประการแรกคือ ในฐานข้อมูลเก็บค่าวันที่อยู่ในรูปของ varchar (Character Varying) + เก็บเป็นพุทธศักราชอีกด้วย ต้องทำการแปลงให้อยู่ในรูปของวันที่เสียก่อน จึงจะเอาไปทำการคำนวณ บวก ลบ คูณ หาร ได้สะดวก คงไม่มีใครเอาตัวแปรแบบ varchar ตั้งแล้วเอา ตัวแปรแบบ varchar ไปลบออกเป็นแน่แท้ ถึงอยากทำก็คงทำไม่ได้&lt;br /&gt;   &lt;/li&gt;&lt;br /&gt;  &lt;/ol&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;เราลองเอาค่าของวันที่มาแตกย่อยดูก่อนเป็นไร ค่าวันที่ที่เก็บในฐานข้อมูลเป็นอย่างนี้ 2548-07-01,11:44:45 (ปี-เดือน-วัน , ชั่วโมง : นาที : วินาที)&lt;/li&gt;&lt;br /&gt; &lt;li&gt;สิ่งที่เราต้องการคือ ปี เดือน วัน เท่านั้น ก็เอาแต่ 2548-07-01 มาเล่น วิธีตัดออกมาเป็นบางช่วงที่เราต้องการคือใช้ฟังก์ชั่น SUBSTRING ช่วย ฟอร์แมตของฟังก์ชั่น SUBSTRING นี้คือ SUBSTRING(text,n1,n2) หรือจะเขียนอีกแบบก็ได้คือ SUBSTRING(text FROM n1 FOR n2) เมื่อ text คือข้อความที่เราต้องการจะตัด , n1 คือตำแหน่งเริ่มต้นที่เราต้องการจะตัดเริ่มจากซ้ายมือ , n2 คือ จำนวนสตริงที่เราต้องการจะตัด &lt;stress1&gt;(n1 และ n2 ต้องเป็นจำนวนเต็มนะครับ ทศนิยมใช้ไม่ได้)&lt;/stress1&gt;&lt;br&gt;&lt;br /&gt; &lt;stress1&gt;For Example&lt;/stress1&gt; &lt;br&gt;&lt;br /&gt;  &lt;ul&gt;&lt;br /&gt;   &lt;li&gt;SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 4) จะได้เท่ากับ 2548 ซึ่งจะได้ค่าออกมาเท่ากับ SUBSTRING(t_visit.visit_financial_discharge_time,1,4) หรือ SUBSTRING(t_visit.visit_financial_discharge_time from 0 for 5)&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;SUBSTRING(t_visit.visit_financial_discharge_time,2,2) ได้เท่ากับ 54 เป็นต้น&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;ลองตัดกันจริงแล้วนะ ฟอร์แมตวันที่ของ PostgreSQL คือ เดือน/วัน/ปี นะครับ ต้องทำให้ถูกต้องด้วย&lt;/li&gt;&lt;br /&gt;    &lt;ul&gt;&lt;br /&gt;     &lt;li&gt;เอาเดือนออกมาก่อน  substring(t_visit.visit_financial_discharge_time from 6 for 2) จะได้เท่ากับ 07 (ยังเป็น text อยู่)&lt;/li&gt;&lt;br /&gt;     &lt;li&gt;ที่นี้ก็เอาวันออกมา substring(t_visit.visit_financial_discharge_time from 9 for 2) จะได้เท่ากับ 01 (ยังเป็น text อยู่)&lt;/li&gt;&lt;br /&gt;     &lt;li&gt;ตามด้วยปี substring(t_visit.visit_financial_discharge_time from 1 for 4) (ยังเป็น text อยู่) เราก็ทำต่อให้เป็นตัวเลขซะเพื่อที่จะแปลงค่าเป็น ค.ศ. ได้ เนื่องจากยังเป็น พ.ศ. อยู่โดย ใช้พังก์ชั่น to_number ครอบ ได้เป็น &lt;stress1&gt;--&gt;&lt;/stress1&gt;to_number(substring(t_visit.visit_financial_discharge_time) ,9999)-543 ก็จะได้เป็น 2005 (2548-543) ตอนนี้เป็นตัวเลขแล้ว&lt;/li&gt;&lt;br /&gt;     &lt;li&gt;ลองเอาสิ่งที่ได้จากที่เราได้ลองตัดสตริงมาต่อกันดูซิด้วยตัวไปป์คู่ (||) ได้ดังนี้&lt;br&gt;&lt;br /&gt;     substring(t_visit.visit_financial_discharge_time from 6 for 2)||'/'||&lt;br&gt;&lt;br /&gt;     substring(t_visit.visit_financial_discharge_time from 9 for 2)||'/'||&lt;br&gt;&lt;br /&gt;     CAST(to_number(substring(t_visit.visit_financial_discharge_time from 1 for 4) ,9999) - 543 AS text) เหตุที่เราต้อง CAST อีกทีก็เพราะว่า 2005 เป็น Numeric ในขณะที่ชาวบ้านเค้าเป็น text กัน ทำให้เป็น text เหมือนกันทั้งสามชุด สมมติว่าชุดนี้คือ เดือน/วัน/ปี  ที่เราตัดสตริงมาเนี่ยมีค่าเป็น  X (X อีกแล้วผมว่าพยัญชนะตัวนี้เหนื่อยที่สุดในโลกเลยก็ว่าได้)&lt;br /&gt;     &lt;/li&gt;&lt;br /&gt;     &lt;li&gt;จากค่า X ที่เราได้มาแล้วก็ต้องมาทำการแปลงให้เป็น varchar อีกครั้งเพื่อสะดวกในการแปลงให้เป็น Date ก็เอา CAST ครอบ X ไปอีกที ได้เป็น&lt;br&gt;&lt;br /&gt;     CAST(x AS varchar) แต่ยังไม่จบได้เป็น varchar แล้ว สมมติให้เป็น Y ต้องแปลงให้เป็น date อีกโดยการใช้ฟังก์ชั่น to_date ครอบ Y อีกที ได้เป็น&lt;br&gt;&lt;br /&gt;     to_date(y,'MM-DD-YYYY') ในวงเล็บระบุด้วยว่าต้องแปลงให้เป็น เดือน-วัน-ปี ด้วยนะ ยุ่งมากมายเลยเนี่ย&lt;/li&gt;&lt;br /&gt;     &lt;li&gt;เมื่อแทนค่า X และ Y ในสมการแล้วก็จะได้เป็นดังนี้&lt;br&gt;&lt;br /&gt;     &lt;pre class=stress&gt;&lt;br /&gt;to_date(CAST(substring(t_visit.visit_financial_discharge_time from 6 for 2)&lt;br /&gt;||'/'||substring(t_visit.visit_financial_discharge_time from 9 for 2)&lt;br /&gt;||'/'||CAST(to_number(substring(t_visit.visit_financial_discharge_time from 1 for 4) ,9999) - 543 AS text) AS varchar),'MM-DD-YYYY')     &lt;br /&gt;     &lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;     &lt;li&gt;ฉันใดก็ฉันนั้นเมื่อเราได้วันที่มารับบริการแล้วก็น่าจะได้วันเกิดของผู้ป่วยด้วย โดยใช้การแทนค่าด้วยตัวแปรเหมือนข้างบน&lt;br&gt;&lt;br /&gt;     &lt;pre class=stress&gt;&lt;br /&gt;to_date(CAST(substring(t_patient.patient_birthday from 6 for 2)&lt;br /&gt;||'/'||substring(t_patient.patient_birthday from 9 for 2)&lt;br /&gt;||'/'||CAST(to_number(substring(t_patient.patient_birthday from 1 for 4) ,9999) - 543 AS text) AS varchar),'MM-DD-YYYY')     &lt;br /&gt;     &lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;     &lt;li&gt;ผมอยากจะบอกว่า ไอ้ที่พูดมาข้างบนน่ะ ผมไม่ได้ทำด้วยตัวเอง ได้รับความอนุเคราะห์จากน้องๆ ที่น่ารัก (โอ๋ , เหน่ง) ทำให้ต่างหาก &lt;/li&gt;&lt;br /&gt;     &lt;li&gt;ความยากลำบากในการที่ต้องแปลงนั่นเป็นนี่ แปลงนี่ให้เป็นนั่น เนื่องมาจากค่าของวันที่นั้น ผมได้ Request ไปในเวอร์ชั่นสามแล้ว แต่ไม่รู้ว่าผลการ Request จะออกมาอย่างไรบ้าง&lt;/li&gt;&lt;br /&gt;     &lt;/ul&gt;&lt;br /&gt;  &lt;/ul&gt; &lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;เมื่อได้วันที่ที่มารับบริการและวันเกิดที่สามารถจะเอาทำการคำนวณได้แล้ว ก็เอาวันที่ที่มารับบริการตั้งแล้วลบด้วยวันเกิด แต่การที่จะทำอย่างนั้นแล้วได้ผลลัพท์ออกมาเลยน่ะ ค่อนข้างยาก และซับซ้อน โชคดีที่มีตัวช่วยอยู่ คือเมื่อก่อนเหน่ง (สุรชัย ต่อวงศ์) ได้ทำฟังก์ชันเกี่ยวกับวันที่ ไว้ให้ผมใช้สองสามอัน ก็เลยเอามาโมดิฟายเล่น เพื่อลดภาระในการเขียน SQL และช่วยในการคำนวณ ฟังก์ชันนี้ผมเรียกว่า &lt;a href=sql/calage3.fnc.sql&gt;ฟังก์ชันแสดงอายุแบบสั้น&lt;/a&gt; สร้างด้วยภาษา plpgsql หน้าตาเป็นอย่างนี้ครับ&lt;br /&gt; &lt;pre class=file&gt;&lt;br /&gt;CREATE OR REPLACE FUNCTION calage3(date,date)&lt;br /&gt;  RETURNS text AS&lt;br /&gt;'DECLARE&lt;br /&gt;  d INTEGER;&lt;br /&gt;  BEGIN&lt;br /&gt;  d:= $1-$2;&lt;br /&gt;  IF d &gt; 365 THEN  RETURN d/365 || \' ป\';&lt;br /&gt;  ELSE&lt;br /&gt;   IF d = 365 THEN  RETURN \'1 ป\';&lt;br /&gt;   ELSE&lt;br /&gt;    IF d &gt; 30 THEN  RETURN d/30 || \' ด\';&lt;br /&gt;    ELSE&lt;br /&gt;     IF d = 30 THEN  RETURN \'1 ด\';&lt;br /&gt;     ELSE&lt;br /&gt;      IF d &gt; 1 THEN  RETURN d || \' ว\';&lt;br /&gt;      ELSE&lt;br /&gt;       IF d = 1 THEN  RETURN \'1 ว\';&lt;br /&gt;       ELSE&lt;br /&gt;        IF d &lt;= 0 THEN  RETURN \'0 ว\';&lt;br /&gt;        END IF;&lt;br /&gt;       END IF;&lt;br /&gt;      END IF;&lt;br /&gt;     END IF;&lt;br /&gt;    END IF;&lt;br /&gt;   END IF;&lt;br /&gt;  END IF;&lt;br /&gt;  RETURN \' \';&lt;br /&gt;  END;'&lt;br /&gt;  LANGUAGE 'plpgsql' VOLATILE; &lt;br /&gt; &lt;/pre&gt;วิธีการก็คือเอาไปฝังไว้ในฐานข้อมูล&lt;br /&gt; &lt;pre class=command&gt;postgres@debian: ~ $ psql your_database &lt; calage3.fnc.sql&lt;/pre&gt;&lt;br /&gt;ฟังก์ชั่นนี้จะสามารถทำงานได้ก็ต่อเมื่อ มีการส่งค่าพารามิเตอร์มาสองค่า จะมากหรือน้อยกั่วนี้ย่อมเป็นไปมิได้เด็ดขาด ค่าแรกที่ต้องส่งมาคือ t_visit.visit_financial_discharge_time และค่าที่สองคือ t_patient.patient_birthday ทั้งนี้ทั้งสองค่าต้องผ่านการแปลงค่าด้วยวิธีการข้างบนเรียบร้อยแล้วด้วยนะ รูปแบบการใช้ฟังก์ชั่นนี้ก็คือ&lt;br&gt;&lt;br /&gt; &lt;pre class=file&gt;calage3(visit_date,birth_date)&lt;/pre&gt;มาดูค่าจริงๆ ที่เราต้องเขียนเป็น SQL ก็คือ&lt;br /&gt; &lt;pre class=file&gt;calage3(to_date(CAST(substring(t_visit.visit_financial_discharge_time from 6 for 2)&lt;br /&gt;||'/'||substring(t_visit.visit_financial_discharge_time from 9 for 2)&lt;br /&gt;||'/'||CAST(to_number(substring(t_visit.visit_financial_discharge_time from 1 for 4) ,9999) - 543 AS text) AS varchar),'MM-DD-YYYY') &lt;br /&gt; ,&lt;br /&gt; to_date(CAST(substring(t_patient.patient_birthday from 6 for 2)&lt;br /&gt;||'/'||substring(t_patient.patient_birthday from 9 for 2)&lt;br /&gt;||'/'||CAST(to_number(substring(t_patient.patient_birthday from 1 for 4) ,9999) - 543 AS text) AS varchar),'MM-DD-YYYY')&lt;br /&gt; ) AS age&lt;/pre&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;เอาล่ะนะ ลองเอามาทำเป็น SQL เต็มๆ ดูบ้าง&lt;br /&gt; &lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) AS date_visit&lt;/span&gt;&lt;br /&gt; ,t_patient.patient_hn AS hn&lt;br /&gt; ,pat_address.patient_name AS name&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;,calage3(to_date(CAST(substring(t_visit.visit_financial_discharge_time from 6 for 2)&lt;br /&gt;||'/'||substring(t_visit.visit_financial_discharge_time from 9 for 2)&lt;br /&gt;||'/'||CAST(to_number(substring(t_visit.visit_financial_discharge_time from 1 for 4) ,9999) - 543 AS text) AS varchar),'MM-DD-YYYY') &lt;br /&gt; ,&lt;br /&gt; to_date(CAST(substring(t_patient.patient_birthday from 6 for 2)&lt;br /&gt;||'/'||substring(t_patient.patient_birthday from 9 for 2)&lt;br /&gt;||'/'||CAST(to_number(substring(t_patient.patient_birthday from 1 for 4) ,9999) - 543 AS text) AS varchar),'MM-DD-YYYY')&lt;br /&gt; ) AS age&lt;/span&gt;&lt;br /&gt; ,pat_address.address AS address&lt;br /&gt; ,t_patient.patient_pid AS pid&lt;br /&gt;FROM&lt;br /&gt; t_patient,pat_address,t_visit,t_diag_icd10&lt;br /&gt;WHERE&lt;br /&gt; t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt; AND t_patient.patient_hn = pat_address.patient_hn&lt;br /&gt; AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt; AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-01-01' and '2548-03-31')          &lt;br /&gt; AND t_patient.patient_hn NOT IN&lt;br /&gt;   ( /* เริ่มต้น */&lt;br /&gt;   SELECT&lt;br /&gt;    DISTINCT(t_patient.patient_hn)&lt;br /&gt;   FROM&lt;br /&gt;    t_patient&lt;br /&gt;    ,t_visit&lt;br /&gt;    ,t_diag_icd10&lt;br /&gt;   WHERE&lt;br /&gt;    t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt;    AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt;    AND t_visit.f_visit_type_id='0'&lt;br /&gt;    AND t_visit.f_visit_status_id='3'&lt;br /&gt;    AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;      OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;      OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;      OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;br /&gt;    AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-01-01' and '2548-02-28')&lt;br /&gt;   ) /* สิ้นสุด */&lt;br /&gt;GROUP BY&lt;br /&gt; hn&lt;br /&gt; ,pat_address.patient_name&lt;br /&gt; ,pat_address.address&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;,t_patient.patient_tambon&lt;br /&gt; ,t_visit.visit_financial_discharge_time&lt;br /&gt; ,t_patient.patient_birthday&lt;/span&gt;&lt;br /&gt; ,t_patient.patient_pid&lt;br /&gt;ORDER BY &lt;span style="color: rgb(255, 0, 0);"&gt;date,&lt;/span&gt;hn&lt;span style="color: rgb(255, 0, 0);"&gt;,t_patient.patient_tambon&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt; ประโยคที่ท่านเห็นเป็นสีแดงคือสิ่งที่เพิ่มเข้าไปใหม่ และต้องเพิ่ม Group By เข้าไปอีกสองสามบรรทัดนะครับ SQL จึงจะทำงานได้สมบูรณ์ ไม่มีเอ๋อเหล๋อ ได้ผลลัพท์อย่างนี้ครับ&lt;br /&gt; &lt;pre class=stress&gt;&lt;br /&gt;2548-03-08    000000435    นางศรี  อินปุ๊ด    53 ป    42  ม.05 ต.วอแก้ว อ.ห้างฉัตร จ.ลำปาง    3510500027099&lt;br /&gt;2548-03-30    000001530    นายแก้ว  วงศ์จันทร์    73 ป    33  ม.07 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500074780&lt;br /&gt;&lt;/pre&gt;ก็จบเรื่องราวของ SUBSTRING , การแปลงค่าด้วยฟังก์ชั่นต่างๆ รวมถึงการใช้งานฟังก์ชั่นที่สร้างขึ้นมาเอง ภาษาฝรั่งตามที่ได้ยินมาเค้าเรียกว่า User Define Function (UDF) ก็คงจะได้ไอเดียเอาเรื่องราวเหล่านี้ไปประยุกต์ใช้ให้เหมาะสมได้ทั่วหน้ากันนะครับ&lt;br /&gt; &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;แหล่งความรู้และอ้างอิง&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;John C. Worsley and Joshua D. Drake, Practical PostgreSQL&lt;br&gt;&lt;br /&gt; O'Reilly &amp; Associates, Inc., CA ,USA &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112573950863514654?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112573950863514654/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112573950863514654' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112573950863514654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112573950863514654'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/08/sql-1_30.html' title='เรื่องของ SQL ตอนที่ 1 เพิ่มเติมอีกหน่อยนึง'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112573889029869154</id><published>2005-08-29T16:09:00.000+07:00</published><updated>2005-09-25T20:30:15.776+07:00</updated><title type='text'>เรื่องของ SQL ตอนที่ 2</title><content type='html'>ตอนที่แล้วเขียนเรื่องเกี่ยวกับ SQL ไปตอนหนึ่งรู้สึกว่า เริ่มมันส์ในอารมณ์ เกิดความกระเหี้ยนกระหืออยากจะเขียนอีก ว่าแล้วก็สนองตัณหาของตัวเองอีกเป็นไรมี ใครคงจะไม่นินทา (ให้ได้ยิน) เป็นแน่แท้ ไหนๆ ก็อยู่กับเรื่อง Sub Query แล้วก็เขียนต่ออีกซะเลย เอาเรื่องเบาหวานนี่แหละ คนอ่านจะได้ต่อเนื่องไม่ต้องเสียเวลาลำดับความคิด ย้อนไปย้อนมา ให้ปวดหมอง&lt;br&gt;&lt;br&gt;&lt;br /&gt;ก่อนที่จะมาเป็น SQL ในตอนที่แล้วเคยได้รับโจทย์จากบรรดาเจ้านาย ที่น่ารักทั้งหลาย เกี่ยวกับคนไข้เบาหวานนี่แหละว่า อยากจะได้รายชื่อคนไข้เบาหวาน ที่อยู่ อายุ และรายละเอียดอีกหลายอย่าง แล้วกำชับด้วยนะว่าเอารหัสออกมาให้ดูด้วย (คงประมาณว่าอยากจะรู้ว่าเรา SELECT มั่วมั่งอะป่าว) ก็ได้สิ จะไปยากอะไรกัน แถมรหัสการวินิจฉัยให้ด้วยก็ยังไหว&lt;br&gt;&lt;br&gt;นี่เลย SQL โชว์ให้ดู เป็น SQL ชุดที่หนึ่งแล้วกัน&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; SUBSTRING(t_visit.visit_financial_discharge_time,0,11) AS DATE&lt;br /&gt; ,t_patient.patient_hn AS hn&lt;br /&gt; ,pat_address.patient_name AS name&lt;br /&gt; ,pat_address.address AS address&lt;br /&gt; ,t_patient.patient_pid AS pid&lt;br /&gt; ,t_diag_icd10.diag_icd10_number AS icd10&lt;br /&gt; ,t_diag_icd10.f_diag_icd10_type_id AS diag_type&lt;br /&gt;FROM&lt;br /&gt; t_patient,pat_address,t_visit,t_diag_icd10&lt;br /&gt;WHERE&lt;br /&gt; t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt; AND t_patient.patient_hn = pat_address.patient_hn&lt;br /&gt; AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt; AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-07-01' and '2548-07-31')&lt;br /&gt;GROUP BY&lt;br /&gt; t_visit.visit_financial_discharge_time&lt;br /&gt; ,hn&lt;br /&gt; ,pat_address.patient_name&lt;br /&gt; ,pat_address.address&lt;br /&gt; ,t_patient.patient_pid&lt;br /&gt; ,t_diag_icd10.diag_icd10_number&lt;br /&gt; ,t_diag_icd10.f_diag_icd10_type_id&lt;br /&gt;ORDER BY hn&lt;br /&gt;&lt;/pre&gt;หรือจะเขียนอีกแบบหนึ่งก็ได้ดังนี้ ตั้งชื่อว่าเป็น SQL ชุดที่สอง&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; SUBSTRING(v.visit_financial_discharge_time,0,11) AS DATE&lt;br /&gt; ,t.patient_hn AS hn&lt;br /&gt; ,p.patient_name AS name&lt;br /&gt; ,p.address AS address&lt;br /&gt; ,t.patient_pid AS pid&lt;br /&gt; ,d.diag_icd10_number AS icd10&lt;br /&gt; ,d.f_diag_icd10_type_id AS diag_type&lt;br /&gt;FROM&lt;br /&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;t_patient t,pat_address p ,t_visit v,t_diag_icd10 d&lt;/span&gt;&lt;br /&gt;WHERE&lt;br /&gt; t.patient_hn = v.visit_hn&lt;br /&gt; AND t.patient_hn = p.patient_hn&lt;br /&gt; AND v.t_visit_id = d.diag_icd10_vn&lt;br /&gt; AND v.f_visit_type_id='0'&lt;br /&gt; AND v.f_visit_status_id='3'&lt;br /&gt; AND (d.diag_icd10_number LIKE 'E10%' &lt;br /&gt;    OR d.diag_icd10_number LIKE 'E11%'&lt;br /&gt;    OR d.diag_icd10_number LIKE 'E14%'&lt;br /&gt;    OR d.diag_icd10_number LIKE 'E15%')&lt;br /&gt; AND (SUBSTRING(v.visit_financial_discharge_time from 1 for 10) between '2548-07-01' and '2548-07-31')&lt;br /&gt;GROUP BY&lt;br /&gt; v.visit_financial_discharge_time&lt;br /&gt; ,hn&lt;br /&gt; ,p.patient_name&lt;br /&gt; ,p.address&lt;br /&gt; ,t.patient_pid&lt;br /&gt; ,d.diag_icd10_number&lt;br /&gt; ,d.f_diag_icd10_type_id&lt;br /&gt;ORDER BY hn&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;สังเกตุที่ตัวสีแดงใน SQL ชุุดที่สองนะครับ ทำไมต้องมี ตัวอักษรตามหลังตารางด้วย อย่างเช่น t_patient ตามด้วย t , pat_address ตามด้วย p ขอเฉลยตรงนี้ครับว่าตัวอักษรที่ตามหลังชื่อตารางคือ alias (ประมาณว่าเป็นชื่อเล่นของตาราง) การกำหนดเราสามารถกำหนดได้ตามใจชอบจะเป็นตัวอักษรหรือคำอะไรก้ได้แต่ไม่น่าจะซ้ำกัน มีประโยชน์ตรงที่เราสามารถจะอ้างอิงใช้ชื่อ alias แทนชื่อของตารางได้เวลาที่เรา จะ SELECT หรืออ้างถึงชื่อตารางเราก็สามารถจะใช้ชื่อ alias แทนได้ เช่นถ้าเราจะพิมพ์ว่า t_patient.hn เราก็อาจจะย่อเป็น t.hn ก็ได้ช่วยลดเวลาการพิมพ์ลงไปได้สำหรับผู้ที่พิมพ์ไม่ค่อยคล่องนัก แต่ก็มีผลเหมือนกันนะครับ อันนี้แล้วแต่ความสะดวกของคนพิมพ์ กับความชอบส่วนตัว ของใครของมัน เอาล่ะ มาต่อกันได้แล้ว ไม่ว่าจะรันด้วย SQL ชุดที่หนึ่งหรือว่าชุดที่สอง ก็จะได้ผลลัพท์ดังนี้&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;2548-07-01    000000435    นางศรี  อินปุ๊ด    42  ม.05 ต.วอแก้ว อ.ห้างฉัตร จ.ลำปาง    3510500027099    E11.9    1&lt;br /&gt;2548-07-02    000020659    นางตา   อุดก้อน    26/1  ม.07 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    3510500009147    E11    1&lt;br /&gt;2548-07-04    000021908    นางบุญทอน  สีสิงห์    88  ม.07 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    3510500012601    E10.9    1&lt;br /&gt;2548-07-04    000009510    นายจันทร์แก้ว  นกแดง    18/1  ม.9 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    3510500057109    E10    1&lt;br /&gt;2548-07-04    000013471    นายสุข  ปุ๊ดแค      38/1  ม.09 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    3510500059349    E11    1&lt;br /&gt;2548-07-06    000019694    นางแว่น   เปี้ยยะ    48  ม.08 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500079676    E11    1&lt;br /&gt;2548-07-06    000019663    นางบุญเย็น  อินมณี    2/1  ม.07 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน        E11    1&lt;br /&gt;2548-07-06    000012629    นางศรีออน  อินมณี     60  ม.08 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500080143    E11    2&lt;br /&gt;2548-07-06    000006196    นางบัวคำ  มีจี๋    57  ม.09 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500158291    E11.4    1&lt;br /&gt;2548-07-07    000009510    นายจันทร์แก้ว  นกแดง    18/1  ม.9 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    3510500057109    E11    1&lt;br /&gt;2548-07-07    000000083    นางจันทร์เป็ง  ใฝนันตา    50  ม.08 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500020779    E11    1&lt;br /&gt;2548-07-07    000024066    นางฟอง  ป้อจุมปู    38/1  ม.02 ต.*บ้านไผ่ อ.ลี้ จ.ลำพูน        E11    1&lt;br /&gt;2548-07-07    000000284    นางหน้อย  ขัดสาร    59  ม.08 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500039038    E11    1&lt;br /&gt;2548-07-07    000000038    นางสุข  เปอร์เขียว    165  ม.06 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500152675    E11    1&lt;br /&gt;2548-07-07    000001082    นางแก้วลูน  อินปุ๊ด    83  ม.06 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500152721    E11    1&lt;br /&gt;2548-07-07    000000959    นายอดุลย์  อุตชมภู    195  ม.03 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500025754    E11    1&lt;br /&gt;2548-07-07    000000435    นางศรี  อินปุ๊ด    42  ม.05 ต.วอแก้ว อ.ห้างฉัตร จ.ลำปาง    3510500027099    E11    1&lt;br /&gt;2548-07-07    000002336    นางวิไลวรรณ  ทองขาว    12/3  ม.15 ต.แม่ตืน อ.ลี้ จ.ลำพูน    3510400354667    E10    1&lt;br /&gt;2548-07-07    000000050    นางสี  สุขเรือง    63  ม.01 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500101965    E11    1&lt;br /&gt;2548-07-07    000018300    นางแพรวพรรณ   ฤทัยธรรม    1979  ม. ต.บางจาก อ.พระโขนง จ.กรุงเทพฯ    3100905452325    E11    4&lt;br /&gt;2548-07-07    000006051    นายอัมรินทร์  เชียงคำ    70  ม.04 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    3510500039283    E10    4&lt;br /&gt;2548-07-07    000002453    นางทองพูน  ทองขาว    242/1  ม.15 ต.แม่ตืน อ.ลี้ จ.ลำพูน    3510400354772    E11    1&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ก็ต้องอภัยสำหรับผู้ป่วยทุกท่านที่บังอาจนำเอาความลับส่วนตัวของท่านมาเผยแพร่ ขอเรียนว่ามิได้มีเจตนาเป็นอย่างอื่นนอกเหนือจากการศึกษา ได้ผลมาแล้วครับ ไม่ยากส์ คิดว่าจบหรือยังล่ะครับ มองเห็นอะไรที่มันทะแม่งๆ หรือปล่าว&lt;br&gt;&lt;br&gt;&lt;br /&gt;ตอนแรกพอผมคิวรี่ได้ปุ๊บก็ส่งผลให้คนที่มาขอไปเลย ไม่ได้คิดอะไร อีกสักพักแกกลับมาครับ หน้างี้บอกว่าใช่เลย คือแกสงสัยว่าคนไข้บางคนรหัสการให้การวินิจฉัยทำไมเป็น 4 (other) บ้าง 2 (Comorbidity) บ้าง ทำไมไม่เป็นหนึ่งเหมือนกันทั้งหมด แล้วคนที่มีรหัสวินิจฉัยเป็นอย่างอื่นนอกจาก 1 (Primary Diagnosis) เนี่ยจะรู้ได้หรือปล่าวว่ามี รหัสโรคอะไรเป็นโรคร่วมได้อีก เอาออกมาให้หมดได้มั๊ย แล้วก็โยนผลการคิวรี่กลับมาให้ผมอย่างแรง ผมไม่ทันจะอธิบายอะไร แกก็ไปเสียแล้ว ทิ้งปริศนาให้ผมขบคิด ก็จริงอย่างที่แกว่า เรามานึกดูเงื่อนไขก็ไม่น่าจะผิดอะไร ก็ SELECT รหัส ICD10 ที่บ่งชี้ว่าเป็นโรคเบาหวานออกมาให้แล้วงัย มานั่งนึกดูอีกทีว่าเราลืมอะไรไปหรือปล่าว &lt;br&gt;&lt;br&gt;&lt;br /&gt;ลืมจริงๆ ครับ ลืมนึกไปว่าก็เรา SELECT ออกมาเฉพาะรหัสโรคทีประกอบด้วย E10 E11 E14 E 15 แต่ผู้ป่วยน่ะไม่จำเป็นว่าเวลามารับการรักษาจะได้รหัสโรคอันเดียวนี่ อาจจะมีโรคร่วมด้วย เช่นปวดเมื่อยกล้ามเนื้อซึ่งเป็นอาการเด่นในการมารับบริการครั้งนั้นก็ได้ ซึ่งรหัสโรคอาจจะมีเท่ากับหนึ่งหรือมากกว่าก็ได้ใช่ป่าว แต่จะทำอย่างไรถึงจะ SELECT ออกมาได้ทั้งหมดและมีรหัสของโรคเบาหวานออกมาด้วย ทำอย่างไรล่ะ (โ.....๊ย)&lt;br&gt;&lt;br&gt;&lt;br /&gt;ใช้หมองหน่อย เป็นอิ๊กคิวซํงอยู่สองสามวันได้ พบว่า&lt;br /&gt;&lt;UL&gt;&lt;br /&gt; &lt;li&gt;ข้อแรก ถ้าเรารู้ว่ามี HN อะไรบ้างที่มีรหัสโรคของเบาหวาน เอาแค่ HN อย่างเดียวพอ อันอื่นไม่เอาก็คงได้ ก็เอา SQL ชุดข้างบนนี่แหละตัดแต่งนิดหน่อย ดังนี้ เป็น SQL ชุดที่สาม&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; t.patient_hn AS hn&lt;br /&gt;FROM&lt;br /&gt; t_patient t,pat_address p ,t_visit v,t_diag_icd10 d&lt;br /&gt;WHERE&lt;br /&gt; t.patient_hn = v.visit_hn&lt;br /&gt; AND t.patient_hn = p.patient_hn&lt;br /&gt; AND v.t_visit_id = d.diag_icd10_vn&lt;br /&gt; AND v.f_visit_type_id='0'&lt;br /&gt; AND v.f_visit_status_id='3'&lt;br /&gt; AND (d.diag_icd10_number LIKE 'E10%' &lt;br /&gt;    OR d.diag_icd10_number LIKE 'E11%'&lt;br /&gt;    OR d.diag_icd10_number LIKE 'E14%'&lt;br /&gt;    OR d.diag_icd10_number LIKE 'E15%')&lt;br /&gt; AND (SUBSTRING(v.visit_financial_discharge_time from 1 for 10) between '2548-07-01' and '2548-07-31')&lt;br /&gt;GROUP BY&lt;br /&gt; hn&lt;br /&gt; ,d.diag_icd10_number&lt;br /&gt; ,d.f_diag_icd10_type_id&lt;br /&gt;ORDER BY hn&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ก็ได้ HN ออกมายาวยืด ดังนี้ (ตัดเอามาให้ดูบางส่วน)&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;"000000038"&lt;br /&gt;"000000050"&lt;br /&gt;"000000083"&lt;br /&gt;"000000164"&lt;br /&gt;"000000216"&lt;br /&gt;"000000284"&lt;br /&gt;"000000330"&lt;br /&gt;"000000435"&lt;br /&gt;"000000435"&lt;br /&gt;"000002095"&lt;br /&gt;"000002336"&lt;br /&gt;"000002453"&lt;br /&gt;"000002938"&lt;br /&gt;"000003553"&lt;br /&gt;"000003553"&lt;br /&gt;"000003566"&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;ข้อต่อมาก็คือ ถ้าเราจะ SELECT รายละเอียดของผู้ป่วยตามโจทย์ของเราออกมา (โดยที่มีรหัสการวินิจฉัยโรคออกมาให้หมด) ก็คงจะเขียน SQL เหมือนกับ SQL ชุดแรก คือชุดที่ยังมีปัญหาอยู่ แต่เราก็คงไม่ต้องระบุว่าให้เอารหัสโรค คือ E10 E11 E14 E15 ออกมาด้วย ก็คงได้ประมาณนี้ โดยตัดเอาบรรทัดที่เป็นสีแดงออกไปซะ แล้วก็ให้เรียงตามวันที่ ตามด้วย HN ตามด้วยรหัสประเภทของการวินิจฉัยซะหน่อย (ORDER BY DATE,HN,diag_type) เป็น SQL ชุดที่สี่&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; SUBSTRING(t_visit.visit_financial_discharge_time,0,11) AS DATE&lt;br /&gt; ,t_patient.patient_hn AS hn&lt;br /&gt; ,pat_address.patient_name AS name&lt;br /&gt; ,pat_address.address AS address&lt;br /&gt; ,t_patient.patient_pid AS pid&lt;br /&gt; ,t_diag_icd10.diag_icd10_number AS icd10&lt;br /&gt; ,t_diag_icd10.f_diag_icd10_type_id AS diag_type&lt;br /&gt;FROM&lt;br /&gt; t_patient,pat_address,t_visit,t_diag_icd10&lt;br /&gt;WHERE&lt;br /&gt; t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt; AND t_patient.patient_hn = pat_address.patient_hn&lt;br /&gt; AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt; AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;/span&gt;&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-07-01' and '2548-07-31')&lt;br /&gt;GROUP BY&lt;br /&gt; t_visit.visit_financial_discharge_time&lt;br /&gt; ,hn&lt;br /&gt; ,pat_address.patient_name&lt;br /&gt; ,pat_address.address&lt;br /&gt; ,t_patient.patient_pid&lt;br /&gt; ,t_diag_icd10.diag_icd10_number&lt;br /&gt; ,t_diag_icd10.f_diag_icd10_type_id&lt;br /&gt;ORDER BY DATE,diag_type&lt;br /&gt;&lt;/pre&gt;ก็ได้ผลตามข้างล่างนี้สังเกตุดูผู้ป่วยที่ชื่อคุณศรีออน อินมณี (วันที่ 6 ) กับคุณแพรวพรรณ ฤทัยธรรม (วันที่ 7) นะครับ (ตัวแดง) เห็นว่าได้รหัสโรคออกมามากกว่าที่เห็นในผลลัพท์แรกแล้ว แต่ปํญหาคือว่ายังมีผู้ป่วยท่านอื่นที่ไม่ได้ป่วยด้วยเบาหวานออกมาด้วยอีก&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;2548-07-01    000000030    นางบัวสาย  กาใจ    131  ม.03 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500023069    M15.0    1&lt;br /&gt;2548-07-01    000000142    นางไพรลิน  ขัดสาร     68  ม.02 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500024642    A09    1&lt;br /&gt;2548-07-01    000000160    นางผัด  ยาแปง    90/5  ม.03 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500115133    M79.1    1&lt;br /&gt;2548-07-01    000000168    นางอำนวย  จุนุ    163  ม.06 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500151610    N64.4    1&lt;br /&gt;2548-07-01    000000435    นางศรี  อินปุ๊ด    42  ม.05 ต.วอแก้ว อ.ห้างฉัตร จ.ลำปาง    3510500027099    E11.9    1&lt;br /&gt;2548-07-01    000000435    นางศรี  อินปุ๊ด    42  ม.05 ต.วอแก้ว อ.ห้างฉัตร จ.ลำปาง    3510500027099    J00    2&lt;br /&gt;...........................&lt;br /&gt;2548-07-06    000012288    นางสาย  บุญเลี้ยง    257/2  ม.15 ต.แม่ตืน อ.ลี้ จ.ลำพูน    3330400850771    R10.0    1&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;2548-07-06    000012629    นางศรีออน  อินมณี     60  ม.08 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500080143    I10    1&lt;br /&gt;2548-07-06    000012629    นางศรีออน  อินมณี     60  ม.08 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500080143    E11    2&lt;/span&gt;&lt;br /&gt;2548-07-06    000012646    ส.ต.ท.เชษฐ์    ก้อนทอง     สภอ.ทุ่งหัวช้าง  ม.02 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน        Z00.0    1&lt;br /&gt;...........................&lt;br /&gt;2548-07-07    000018204    นายภาสกร   เต๋จา    185/1  ม.04 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    1510500032533    S05.0    1&lt;br /&gt;2548-07-07    000018204    นายภาสกร   เต๋จา    185/1  ม.04 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    1510500032533    W20.09    5&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;2548-07-07    000018300    นางแพรวพรรณ   ฤทัยธรรม    1979  ม. ต.บางจาก อ.พระโขนง จ.กรุงเทพฯ    3100905452325    I10    1&lt;br /&gt;2548-07-07    000018300    นางแพรวพรรณ   ฤทัยธรรม    1979  ม. ต.บางจาก อ.พระโขนง จ.กรุงเทพฯ    3100905452325    E11    4&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;2548-07-07    000018486    นางจันทิมา    แปงตำ    109/1  ม.02 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    2500400019363    Z34.8    1&lt;br /&gt;2548-07-07    000018486    นางจันทิมา    แปงตำ    109/1  ม.02 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    2500400019363    Z71.7    2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;สรุปแล้ว จาก SQL ชุดที่สี่ ถ้าหากว่าเราสามารถเพิ่มเงื่อนไขตรง WHERE ให้เอาเฉพาะ HN ที่ได้จาก SQL ชุดที่สาม ก็น่าจะได้ผลลัพท์ที่ เริ่ด เลอ เพอร์เฟ็ค เป๊ะมั๊ยทีนี้ ไม่เชื่อถามอาจารย์ประมาณ หรืออาจารย์วันชัย (รายการคนหัวหมอ) ก็ได้ เอาชุดที่สามเป็น SUB Query ซะ แล้วก็ใช้ Operator ชนิด IN  ช่วย ร่างให้ดูก่อนก็ได้&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; SUBSTRING(t_visit.visit_financial_discharge_time,0,11) AS DATE&lt;br /&gt; ,t_patient.patient_hn AS hn&lt;br /&gt; ,pat_address.patient_name AS name&lt;br /&gt; ,pat_address.address AS address&lt;br /&gt; ,t_patient.patient_pid AS pid&lt;br /&gt; ,t_diag_icd10.diag_icd10_number AS icd10&lt;br /&gt; ,t_diag_icd10.f_diag_icd10_type_id AS diag_type&lt;br /&gt;FROM&lt;br /&gt; t_patient,pat_address,t_visit,t_diag_icd10&lt;br /&gt;WHERE&lt;br /&gt; t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt; AND t_patient.patient_hn = pat_address.patient_hn&lt;br /&gt; AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-07-01' and '2548-07-31')&lt;br /&gt; AND t_patient.patient_hn &lt;span style="color: rgb(255, 0, 0);"&gt;IN&lt;/span&gt;&lt;br /&gt; ( /* เริ่ม SQL ชุดที่สาม */&lt;br /&gt;  SELECT&lt;br /&gt;   t.patient_hn AS hn&lt;br /&gt;  FROM&lt;br /&gt;   t_patient t,pat_address p ,t_visit v,t_diag_icd10 d&lt;br /&gt;  WHERE&lt;br /&gt;   t.patient_hn = v.visit_hn&lt;br /&gt;   AND t.patient_hn = p.patient_hn&lt;br /&gt;   AND v.t_visit_id = d.diag_icd10_vn&lt;br /&gt;   AND v.f_visit_type_id='0'&lt;br /&gt;   AND v.f_visit_status_id='3'&lt;br /&gt;   AND (d.diag_icd10_number LIKE 'E10%' &lt;br /&gt;      OR d.diag_icd10_number LIKE 'E11%'&lt;br /&gt;      OR d.diag_icd10_number LIKE 'E14%'&lt;br /&gt;      OR d.diag_icd10_number LIKE 'E15%')&lt;br /&gt;   AND (SUBSTRING(v.visit_financial_discharge_time from 1 for 10) between '2548-07-01' and '2548-07-31')&lt;br /&gt;  GROUP BY&lt;br /&gt;   hn&lt;br /&gt;   ,d.diag_icd10_number&lt;br /&gt;   ,d.f_diag_icd10_type_id&lt;br /&gt;  ORDER BY hn  /* สิ้นสุด SQL ชุดที่สาม */&lt;br /&gt; )&lt;br /&gt;GROUP BY&lt;br /&gt; t_visit.visit_financial_discharge_time&lt;br /&gt; ,t_patient.patient_hn&lt;br /&gt; ,pat_address.patient_name&lt;br /&gt; ,pat_address.address&lt;br /&gt; ,t_patient.patient_pid&lt;br /&gt; ,t_diag_icd10.diag_icd10_number&lt;br /&gt; ,t_diag_icd10.f_diag_icd10_type_id&lt;br /&gt;ORDER BY DATE,t_patient.patient_hn,diag_type&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;อิ อิ ดูผลลัพท์เปรียบเทียบกันกับผลลัพท์ที่ได้จากชุดแรก&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;2548-07-06    000006196    นางบัวคำ  มีจี๋    57  ม.09 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500158291    E11.4    1&lt;br /&gt;2548-07-06    000007187    นางสาวเสาวรีย์  หล้าเป็ง    65  ม.05 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    3510500045429    E10.9    1&lt;br /&gt;2548-07-06    000007431    นางเงิน  สุปี    143  ม.05 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    3510500045399    E10.9    1&lt;br /&gt;2548-07-06    000008221    นางทองไพร   มันจา    60  ม.09 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500160252    E11    1&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;2548-07-06    000012629    นางศรีออน  อินมณี     60  ม.08 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500080143    I10    1&lt;br /&gt;2548-07-06    000012629    นางศรีออน  อินมณี     60  ม.08 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500080143    E11    2&lt;/span&gt;&lt;br /&gt;2548-07-06    000013110    ด.ต.วิชัย   มะโนวงศ์    สภอ.ทุ่งหัวช้าง  ม.02 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3580200103326    Z00    1&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;2548-07-07    000018300    นางแพรวพรรณ   ฤทัยธรรม    1979  ม. ต.บางจาก อ.พระโขนง จ.กรุงเทพฯ    3100905452325    I10    1&lt;br /&gt;2548-07-07    000018300    นางแพรวพรรณ   ฤทัยธรรม    1979  ม. ต.บางจาก อ.พระโขนง จ.กรุงเทพฯ    3100905452325    E11    4&lt;/span&gt;&lt;br /&gt;2548-07-07    000019330    นางบัวคำ   ทานา    40  ม.1 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500010113    E11    1&lt;br /&gt;2548-07-07    000019330    นางบัวคำ   ทานา    40  ม.1 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500010113    M79.1    2&lt;br /&gt;2548-07-07    000020603    นายดอก   คำแก้ง    70  ม.5 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500138206    E11    1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;กิ๊บ เก๋ ยูเรก้า ไปเลยครับท่านผู้ชม ข้อกฏหมายไม่มีพลิกอีกแล้ว เฉพาะ SUB Query กับ Operator ชนิด IN กับ NOT IN เนี่ยก็เอาไปหากินได้เยอะแยะ เช่นหาผู้ป่วยในหรือนอกเขตบริการของสถานพยาบาล ทีนี้ก็หวานหมู&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/UL&gt;&lt;br /&gt;ก็จบไปสำหรับเรื่องราวมหาวิบาก ที่ได้ประสบพบพาน เอามาเล่าสู่กันฟัง ผมเองถูกมองว่าเป็นเซียนบ้างล่ะ ผู้เชี่ยวชาญบ้างล่ะ แต่ความจริงไม่ใช่ ก็เป็นยูสเซอร์ธรรมดาเหมือนๆกับท่านทั้งหลายแหละครับ ยังมีคนที่เก่งกว่าผมอีกมากนัก อาศัยลูกตื้อ อ่านให้มาก ทำให้เยอะ ลองผิดบ้างถูกบ้าง พอเราเริ่มเข้าใจแล้ว มันก็จะทำให้เราหาทางแก้ปัญหาที่เข้ามาได้เร็วขึ้น เนียนขึ้น อย่าพึ่งยอมแพ้ อาจจะต้องหาเวลาส่วนตัวให้มากขึ้นกว่าเดิม ของอย่างนี้ต้องใช้เวลาบ้างนะครับ ต้องยอมนอนดึกกว่าปกติ เล่นเกมส์ที่ชอบน้อยลง คุยโทรศัพท์กับกิ๊กน้อยลง แล้วความสำเร็จก็จะเป็นของเรา ขอให้กำลังใจกับทุกท่านครับ เราทำเองเราได้เอง โปรดติดตามตอนต่อไปนะครับ น่าสนใจทีเดียวแหละ เป็นเรื่องราวของ น้องจอย (JOIN) เกริ่นให้ฟังยั่วน้ำลายเล่นๆ ไปก่อน&lt;br /&gt;&lt;br /&gt;&lt;br&gt;&lt;BR&gt;&lt;BR&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;แหล่งความรู้และอ้างอิง&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;John C. Worsley and Joshua D. Drake, Practical PostgreSQL&lt;br&gt;&lt;br /&gt; O'Reilly &amp; Associates, Inc., CA ,USA &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112573889029869154?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112573889029869154/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112573889029869154' title='2 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112573889029869154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112573889029869154'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/08/sql-2.html' title='เรื่องของ SQL ตอนที่ 2'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16185897.post-112573838274362337</id><published>2005-08-08T15:59:00.000+07:00</published><updated>2005-09-25T19:39:04.386+07:00</updated><title type='text'>เรื่องของ SQL ตอนที่ 1</title><content type='html'>ตอนบ่ายเข้าไปที่เวบ เห็นมีเพื่อนสมาชิกท่านหนึ่งกำลังกังวล เกี่ยวกับการจัดทำระเบียนผู้ป่วยโรคเบาหวานว่าต้องการรายชื่อผู้ป่วยเบาหวานออกมาโดยไม่ให้ชื่อซ้ำกัน หรือง่ายๆก็คือนับเฉพาะผู้ป่วยรายใหม่เท่านั้น ก็เลยลองมานั่งคิดว่า คนถึกอย่างเราพอจะทำได้อ่ะป่าว ลองดูน่ะ&lt;br&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;ประการแรกรายชื่อผู้ป่วยเบาหวานโดยไม่ให้ซ้ำชื่อกัน ดูๆ แล้วไม่น่าจะลำบากอะไรนัก แล้วจะเอาอะไรบ้างล่ะ&lt;br /&gt; &lt;ol&gt;&lt;br /&gt;  &lt;li&gt;HN ได้จากตาราง t_patient&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;เลขประจำตัวประชาชน 13 หลัก จาก ตาราง t_patient&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;ชื่อ ได้จากตาราง &lt;a href=sql/pat_address.sql&gt;pat_address&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;ที่อยู่ ก็ได้จาก pat_address พอแค่นี้ก่อนก็แล้วกัน&lt;/li&gt;  &lt;br /&gt; &lt;/ol&gt;&lt;br /&gt; เงื่อนไขที่ใช้ก็ ผู้ป่วยนอกที่จบกระบวนการแล้ว ตั้งแต่วันที่ ถึงวันที่ แล้วเอาเฉพาะผู้ป่วยเบาหวาน (รหัส ICD10 ก็น่าจะเป็น E10 ,E11 ,E14 ,E15) โอเชตามนี้ก็ลงมือ ลุยเลย ได้ SQL มาแบบนี้แหล่ะ&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt;&lt;br /&gt; t_patient.patient_hn AS hn&lt;br /&gt;&lt;br /&gt; ,pat_address.patient_name AS name&lt;br /&gt;&lt;br /&gt; ,pat_address.address AS address&lt;br /&gt;&lt;br /&gt; ,t_patient.patient_pid AS pid&lt;br /&gt;&lt;br /&gt;FROM&lt;br /&gt;&lt;br /&gt; t_patient,pat_address,t_visit,t_diag_icd10&lt;br /&gt;&lt;br /&gt;WHERE&lt;br /&gt;&lt;br /&gt; t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt;&lt;br /&gt; AND t_patient.patient_hn = pat_address.patient_hn&lt;br /&gt;&lt;br /&gt; AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt;&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt;&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt;&lt;br /&gt; AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;br /&gt;&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-01-01' and '2548-03-31')&lt;br /&gt;&lt;br /&gt;GROUP BY&lt;br /&gt;&lt;br /&gt; hn&lt;br /&gt;&lt;br /&gt; ,pat_address.patient_name&lt;br /&gt;&lt;br /&gt; ,pat_address.address&lt;br /&gt;&lt;br /&gt; ,t_patient.patient_pid&lt;br /&gt;&lt;br /&gt;ORDER BY hn&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;ก็ได้ผลลัพท์ออกมาตามต้องการ ความจริงมีเยอะกว่านี้เอามาให้ดูแค่ช่วงเดียว&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt;  000000038    นางสุข  เปอร์เขียว    165  ม.06 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500152675  &lt;br /&gt;  000000050    นางสี  สุขเรือง    63  ม.01 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500101965  &lt;br /&gt;  000000083    นางจันทร์เป็ง  ใฝนันตา    50  ม.08 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500020779  &lt;br /&gt;  000000138    นายโยง  ผัดดอก    48  ม.12 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    3510500042331  &lt;br /&gt;  000000164    นางเมือง  ทาวี    24/1  ม.01 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500099367  &lt;br /&gt;  000000216    นายฑูรย์  มะโนชัย    108  ม.07 ต.ตะเคียนปม อ.ทุ่งหัวช้าง จ.ลำพูน    3510500013187  &lt;br /&gt;  000000284    นางหน้อย  ขัดสาร    59  ม.08 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500039038  &lt;br /&gt;  000000330    นางมิ่ง  ตายะ    7/1  ม.06 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500026718  &lt;br /&gt;  000000521    นางจันทร์เป็ง  มะโนเนือง    3  ม.08 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500077819  &lt;br /&gt;  000000853    นายหล้า  ใต้ตา    65/2  ม.06 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน      &lt;br /&gt;  000000959    นายอดุลย์  อุตชมภู    195  ม.03 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500025754  &lt;br /&gt;  000001041    นางปัน  วงศ์ศรีใส    92/1  ม.08 ต.ทุ่งหัวช้าง อ.ทุ่งหัวช้าง จ.ลำพูน    3510500019967&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;แต่ลองมาคิดให้ละเอียดอีกที ก็พบว่ายังหลวมไปหน่อย คือถ้าหากว่าเรา ใช้เงื่อนไขนี้กับช่วงเวลาที่มากๆ หลายๆ เดือน ก็อาจจะพบว่าผู้ป่วยในเดือนก่อนๆ ก็จะแสดงผลออกมาด้วย แทนที่จะเป็นผู้ป่วยรายใหม่ตามที่ต้องการ เริ่มรู้สึกว่ายากขึ้นมาหน่อยๆ แล้ว&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;ทีนี้จะหาผู้ป่วยใหม่ได้อย่างไร นึกๆ ดูตาม common sense ถ้าหากว่าเราต้องการหา HN ผู้ป่วยใหม่ (เริ่มมารับบริการตั้งแต่ 1 มีนาคม - 31 มีนาคม) เอาง่ายๆว่าหา HN ของเดือนมีนาคม เราก็ต้องรู้ว่า HN ของผู้ป่วยเบาหวานตั้งแต่ 1 มกราคม ถึง 31 มีนาคม มี HN อะไรบ้าง (X) และก็ต้องรู้ว่าตั้งแต่ 1 มกราคม - 28 กุมภาพันธ์ มี HN อะไรบ้าง (Y) ได้สองข้อนี้เราก็จบ เราก็เลือก HN เอาที่มีใน X แต่ไม่มีใน Y ซะก็สิ้นเรื่อง ซึ่งอาจจะมีหรือไม่มีก็ได้ (ไม่แปลก) ถ้าไม่มีก็แสดงว่าไม่มีผู้ป่วยใหม่ ถ้ามีก็มี  เราก็ใช้ SQL ข้างบนนั่นอีกทีดีกว่าแต่ตอนนี้เราคงเลือกเอาเฉพาะ HN มาอันเดียวแต่เงื่อนไขและช่วงเวลาแตกต่างกันไป สมมติว่า SQL ข้างล่างนี้เป็นชุดที่สองก็แล้วกัน สังเกตุวันที่นะครับ&lt;br&gt;&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt;&lt;br /&gt; DISTINCT(t_patient.patient_hn) AS hn&lt;br /&gt;&lt;br /&gt;FROM&lt;br /&gt;&lt;br /&gt; t_patient&lt;br /&gt;&lt;br /&gt; ,t_visit&lt;br /&gt;&lt;br /&gt; ,t_diag_icd10&lt;br /&gt;&lt;br /&gt;WHERE&lt;br /&gt;&lt;br /&gt; t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt;&lt;br /&gt; AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt;&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt;&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt;&lt;br /&gt; AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;br /&gt;&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-08-01' and '2548-08-28')&lt;br /&gt;&lt;br /&gt;ORDER BY hn&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ทำไมต้องมี DISTINCT ด้วยก็เพราะว่าต้องการไม่ให้ HN ซ้ำอย่างไรเล่าถ้าไม่ใช้ DISTINCT HN อาจจะออกมาซ้ำกันก็ได้ หรือจะใช้แบบไม่มี DISTINCT ก็ต้อง GROUP  HN ด้วยเหมือนข้างล่างนี้&lt;br&gt;&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt; t_patient.patient_hn AS hn&lt;br /&gt;FROM&lt;br /&gt; t_patient&lt;br /&gt; ,t_visit&lt;br /&gt; ,t_diag_icd10&lt;br /&gt;WHERE&lt;br /&gt; t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt; AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt; AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-08-01' and '2548-08-28')&lt;br /&gt;GROUP BY hn&lt;br /&gt;ORDER BY hn&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ก็ได้ผลเหมือนกัน&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;เอาล่ะเมื่อเราได้ค่า X ค่า Y เรียบร้อยแล้วก็เอา SQL ชุดที่หนึ่งมาดัดแปลงอีกหน่อย โดยเพิ่มเงื่อนไขเข้าไปตรง WHERE อีกนิดเดียว ว่า HN ที่เรา SELECT มาในชุดที่หนึ่งต้องไม่มีใน HN ของที่เรา SELECT ออกมาจากชุดสอง เราจะใช้ SUB Query เข้ามาช่วย โดยให้ SQL ชุดที่สองเป็น SUB Query ซะ บวกกับใช้ NOT IN (Operator Precedence) ลองร่างๆ ดูหน่อยซิ&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt;&lt;br /&gt; t_patient.patient_hn AS hn&lt;br /&gt;&lt;br /&gt; ,pat_address.patient_name AS name&lt;br /&gt;&lt;br /&gt; ,pat_address.address AS address&lt;br /&gt;&lt;br /&gt; ,t_patient.patient_pid AS pid&lt;br /&gt;&lt;br /&gt;FROM&lt;br /&gt;&lt;br /&gt; t_patient,pat_address,t_visit,t_diag_icd10&lt;br /&gt;&lt;br /&gt;WHERE&lt;br /&gt;&lt;br /&gt; t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt;&lt;br /&gt; AND t_patient.patient_hn = pat_address.patient_hn&lt;br /&gt;&lt;br /&gt; AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt;&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt;&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt;&lt;br /&gt; AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;br /&gt;&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-01-01' and '2548-03-31')&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt; /* เงือนไขที่เราจะเพิ่มเข้าไป */&lt;br /&gt; AND t_patient.hn NOT IN (SQL ชุดที่สอง)&lt;br /&gt; /* จบเงื่อนไข */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;GROUP BY&lt;br /&gt;&lt;br /&gt; hn&lt;br /&gt;&lt;br /&gt; ,pat_address.patient_name&lt;br /&gt;&lt;br /&gt; ,pat_address.address&lt;br /&gt;&lt;br /&gt; ,t_patient.patient_pid&lt;br /&gt;&lt;br /&gt;ORDER BY hn&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ดู SQL ที่เราจะใช้กันจริงๆ ดีกว่า&lt;br /&gt;&lt;pre class=file&gt;&lt;br /&gt;SELECT&lt;br /&gt;&lt;br /&gt; t_patient.patient_hn AS hn&lt;br /&gt;&lt;br /&gt; ,pat_address.patient_name AS name&lt;br /&gt;&lt;br /&gt; ,pat_address.address AS address&lt;br /&gt;&lt;br /&gt; ,t_patient.patient_pid AS pid&lt;br /&gt;&lt;br /&gt;FROM&lt;br /&gt;&lt;br /&gt; t_patient,pat_address,t_visit,t_diag_icd10&lt;br /&gt;&lt;br /&gt;WHERE&lt;br /&gt;&lt;br /&gt; t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt;&lt;br /&gt; AND t_patient.patient_hn = pat_address.patient_hn&lt;br /&gt;&lt;br /&gt; AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt;&lt;br /&gt; AND t_visit.f_visit_type_id='0'&lt;br /&gt;&lt;br /&gt; AND t_visit.f_visit_status_id='3'&lt;br /&gt;&lt;br /&gt; AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;&lt;br /&gt;    OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;br /&gt; AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-01-01' and '2548-03-31')          &lt;br /&gt;&lt;br /&gt; AND t_patient.patient_hn NOT IN&lt;br /&gt;&lt;br /&gt;   ( /* เริ่มต้น */&lt;br /&gt;   SELECT&lt;br /&gt;&lt;br /&gt;    DISTINCT(t_patient.patient_hn)&lt;br /&gt;&lt;br /&gt;   FROM&lt;br /&gt;&lt;br /&gt;    t_patient&lt;br /&gt;&lt;br /&gt;    ,t_visit&lt;br /&gt;&lt;br /&gt;    ,t_diag_icd10&lt;br /&gt;&lt;br /&gt;   WHERE&lt;br /&gt;&lt;br /&gt;    t_patient.patient_hn = t_visit.visit_hn&lt;br /&gt;&lt;br /&gt;    AND t_visit.t_visit_id = t_diag_icd10.diag_icd10_vn&lt;br /&gt;&lt;br /&gt;    AND t_visit.f_visit_type_id='0'&lt;br /&gt;&lt;br /&gt;    AND t_visit.f_visit_status_id='3'&lt;br /&gt;&lt;br /&gt;    AND (t_diag_icd10.diag_icd10_number LIKE 'E10%' &lt;br /&gt;&lt;br /&gt;      OR t_diag_icd10.diag_icd10_number LIKE 'E11%'&lt;br /&gt;&lt;br /&gt;      OR t_diag_icd10.diag_icd10_number LIKE 'E14%'&lt;br /&gt;&lt;br /&gt;      OR t_diag_icd10.diag_icd10_number LIKE 'E15%')&lt;br /&gt;&lt;br /&gt;    AND (SUBSTRING(t_visit.visit_financial_discharge_time from 1 for 10) between '2548-01-01' and '2548-02-28')&lt;br /&gt;&lt;br /&gt;   ) /* สิ้นสุด */&lt;br /&gt;&lt;br /&gt;GROUP BY&lt;br /&gt;&lt;br /&gt; hn&lt;br /&gt;&lt;br /&gt; ,pat_address.patient_name&lt;br /&gt;&lt;br /&gt; ,pat_address.address&lt;br /&gt;&lt;br /&gt; ,t_patient.patient_pid&lt;br /&gt;&lt;br /&gt;ORDER BY hn&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ก็จะได้ผลลัพท์ออกมาประมาณนี้&lt;br /&gt;&lt;pre class=stress&gt;&lt;br /&gt; 000000435       นางศรี  อินปุ๊ด       42  ม.05 ต.วอแก้ว อ.ห้างฉัตร จ.ลำปาง       3510500027099 &lt;br /&gt; 000001530       นายแก้ว  วงศ์จันทร์       33  ม.07 ต.บ้านปวง อ.ทุ่งหัวช้าง จ.ลำพูน       3510500074780 &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ไม่ยากใช่ไหมครับ ถ้ารู้แนวทางนี้แล้ว อาจนำไปประยุกต์ไช้ได้อีกมากมาย หลากหลาย แต่มีข้อควรระวัง อยู่ว่า SQL ที่เราจะนำมาทำเป็น SUB Query นั้นเราสามารถที่จะ SELECT ออกมาได้เพียงค่าเดียวเท่านั้นนะครับ เหมือนที่ผม SELECT เอาแค่ HN ออกมาค่าเดียวใน SQL ในชุดที่สอง อีกประการหนึ่งก็คือว่าถ้าหากต้องการหารายละเอียดผู้ป่วยเดือนมกราคมแล้วล่ะก็ ใช้แค่ SQL ชุดที่หนึ่งก็พอเพียงแล้ว&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;ส่วนวิธีการสร้างตาราง pat_address ก็ทำได้โดยการโหลดไฟล์ &lt;a href=sql/pat_address.sql&gt;pat_address.sql&lt;/a&gt;  แล้วก็เอาไปไว้ที่ home ของ postgres แล้วก็&lt;br /&gt;&lt;pre class=command&gt;postgres@debian:~$ psql your_database &lt; pat_address.sql&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ความจริงเป็นวิว (view) ครับไม่ใช่ตารางจริงๆ แต่เป็นตารางที่ทำขึ้นมาเทียมๆ (Pseudo Table) เพื่อช่วยให้การคิวรี่อะไรง่ายขึ้น&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;แหล่งความรู้และอ้างอิง&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;John C. Worsley and Joshua D. Drake, Practical PostgreSQL&lt;br&gt;&lt;br /&gt; O'Reilly &amp; Associates, Inc., CA ,USA &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16185897-112573838274362337?l=iamuthai.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iamuthai.blogspot.com/feeds/112573838274362337/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=16185897&amp;postID=112573838274362337' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112573838274362337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16185897/posts/default/112573838274362337'/><link rel='alternate' type='text/html' href='http://iamuthai.blogspot.com/2005/08/sql-1.html' title='เรื่องของ SQL ตอนที่ 1'/><author><name>myNameISuthai</name><uri>http://www.blogger.com/profile/17899569389982095922</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15292891565164077600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>