ปรับปรุงข้อมูลวันหยุดราชการ (Holiday) กัน

สำหรับประชาชนคนไทยแล้วคำว่า “ในเวลาราชการ” นี่น่าจะคุ้นเคยกันเป็นอย่างดี เรามักเห็นคำนี้ติดตามหน่วยงานราชการ แล้วคำว่าในเวลาราชการนี่มันยังไง เอาแบบกำปั้นทุบดิน ก็คือวันที่ไม่ใช่วันหยุดราชการนั่นแหล่ะ 😛

แล้ววันหยุดราชการนี่เราก็เริ่มยึดตาม “ประกาศกำหนดวันหยุดราชการนักขัตฤกษ์ พระพุทธศักราช ๒๔๕๖” ซึ่งพระบาทสมเด็จพระมงกุฎเกล้าเจ้าอยู่หัว รัชกาลที่ ๖ ทรงออกประกาศดังกล่าว ถ้าใครจะศึกษารายละเอียดบล็อกนี้ก็อธิบายไว้เป็นอย่างดี

ทีนี้ตัวที่เกี่ยวข้องกับโรงพยาบาลยังไงบ้าง หลาย ๆ หน่วยงานที่มีระบบคอมพิวเตอร์ไว้ทำงานอย่างเช่นโรงพยาบาล หน่วยบริการหรืออื่น ๆ นี่ก็มักมีตารางวันหยุดในปีนั้น ๆ สำหรับการทำงาน ซึ่งก็จะเป็นตาราง ตารางนึงตามแต่ละเวนเดอร์ (Vendor) สร้างขึ้นรายละเอียดแตกต่างกันบ้าง แต่ส่วนใหญ่แล้ววัตถุประสงค์ก็เพื่อระบุว่าวันใดคือวันหยุดราชการนั่นแหล่ะ ปกติหน้าที่อัพเดตข้อมูลนี้ก็จะเป็นของผู้ดูแลระบบของหน่วยบริการ ข้อมูลพวกนี้ส่วนใหญ่ก็มาจาก ประกาศทางราชการหรือเว็บทั่ว ๆ ไป เช่น วิกิพีเดีย

และอีกเว็บไซต์ก็ myhora ซึ่งมีบริการ iCal บริการ

จะเห็นได้ว่ามีไฟล์ CSV (Comma-separated values) ให้เราได้ใช้ด้วย งั้นเราก็มาปรับปรุงวันหยุดราชการด้วยไฟล์ตัวนี้กัน

  1. เริ่มต้นก็ดาวน์โหลดมาซะ
    wget -O th_holiday.csv http://www.myhora.com/calendar/ical/holiday.aspx?2561.csv

    หน้าตาข้อมูลไฟล์คร่าว ๆ ก็ประมาณนี้

  2. นำเข้าข้อมูลข้างต้นลงในฐานข้อมูลของเราด้วยคำสั่ง LOAD DATA INFILE (สร้างตารางชั่วคราว th_holiday ไว้รอรับด้วย )
    DROP TABLE IF EXISTS th_holiday;
    CREATE TABLE IF NOT EXISTS th_holiday(
        Subject       	VARCHAR(255) NULL
        ,Start_Date    	DATE NOT NULL
        ,Start_Time    	TIME NULL
        ,End_Date      	DATE NULL
        ,End_Time      	TIME NULL
        ,All_day_event 	VARCHAR(4) NOT NULL
        ,Description   	VARCHAR(255) NOT NULL
        ,Show_time_as  	INTEGER  NOT NULL
        ,Location      	VARCHAR(30)
    );
    
    TRUNCATE th_holiday;
    LOAD DATA LOCAL INFILE 'th_holiday.csv' 
    INTO TABLE th_holiday
    FIELDS TERMINATED BY ',' 
    ENCLOSED BY '"'
    ESCAPED BY '"'
    LINES TERMINATED BY '\r\n'
    (`Subject`, @start_date, `Start_Time`, `End_Date`, `End_Time`, `All_day_event`, `Description`, `Show_time_as`, `Location`)
    SET start_date = STR_TO_DATE(@start_date, '%d/%m/%Y');
  3. เป็นอันเสร็จสิ้น ทีนี้ก็นำข้อมูลนี้ไปปรับปรุงในตารางของแต่ละ HIS

 

 

Dockerized Primitive Pictures – Reproducing images with vector-based geometric primitives

มีโปรเจคบน github ที่ใช้สร้างรูปภาพด้วย geometric primitives สำหรับใครที่ชอบรูปภาพแบบนี้จะรู้สึกแบบฟินมากที่มีโปรเจคนี้ขึ้นมา ปรบมือให้เลยหล่ะกัน 👏 👏 👏 👏 👏
ภาพ geometric primitives คือ ? จะอธิบายไงดีให้ภาพมันอธิบายตัวเองหล่ะกัน

รูปใหญ่ ๆ ก็จะประมาณนี้ สวยใช่ไหมล่ะ ^_^

ใครอยากตามไป Fork ก็ตามนี้เลย https://github.com/fogleman/primitive  ส่วนเราก็มาลองสร้าง Docker กัน

  1. เราใช้ Image จาก Go (golang) is a general purpose, higher-level, imperative programming language
FROM golang:alpine
MAINTAINER M
LABEL version="latest"

RUN apk add --no-cache git && \
mkdir -p /opt && cd /opt && \
go get -u github.com/fogleman/primitive

VOLUME /opt
WORKDIR /opt

CMD ["/bin/sh"]
  • มาลองใช้งานกัน
    docker run -it --rm -v /path/data:/opt primative:alpine primitive -i input.png -o output.png -n 100
  • มาดูผลลัพธ์กัน
  • ชอบ ๆ ๆ 😍😍😍😍

เหมือนเพิ่งผ่านไปเมื่อวาน

วันนี้ก็ครบหนึ่งสัปดาห์ของการจากไปของมังกี้ เราแทบจะบรรยายไม่ได้เลยว่าความรู้สึกมันแย่ขนาดไหน และเอาเข้าจริง ๆ ก็ไม่ได้เรียนรู้ธรรมะ สัจธรรมหรือความจริงของโลกอะไรจากการสูญเสียครั้งนี้หรอก แค่หวังว่าชีวิตจะมีสติในเร็ววัน

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

รักและคิดถึงเสมอ…

การหาปีงบประมาณแบบไทยสำหรับ MySQL

ปีงบประมาณ หรือ ปีงบการเงิน (อังกฤษ: fiscal year, financial year หรือ budget year) เป็นช่วงเวลาที่ใช้สำหรับคำนวณงบการเงินประจำปีในธุรกิจและองค์กรอื่น ๆ ในหลายเขตอำนาจตามกฎหมาย กฎข้อบังคับเกี่ยวกับการบัญชีและการเก็บภาษี จะต้องอาศัยรายงานเหล่านี้อย่างน้อยครั้งหนึ่งต่อสิบสองเดือน แต่ไม่จำเป็นว่าช่วงเวลาที่รายงานนี้จะต้องตรงกับปีตามปฏิทิน ซึงปีงบประมาณของไทยเริ่มตั้งแต่เดือนตุลาคมถึงเดือนกันยายนของปีถัดไป

เราสามารถเขียนฟังก์ชั่น (Function) เพื่อคำนวณหาปีงบประมาณจากฐานข้อมูล MySQL ตามนี้

DELIMITER $$

DROP FUNCTION IF EXISTS THGOVYEAR$$
CREATE FUNCTION THGOVYEAR(
    xdate DATETIME,
    th BIT)
RETURNS INT 
DETERMINISTIC
BEGIN
    RETURN IF(MONTH(xdate) < 10, YEAR(xdate), YEAR(DATE_ADD(xdate, INTERVAL 1 YEAR))) + (543*th);
END$$

DELIMITER ;

โดยตัวแปรที่รับในฟังก์ชั่นเองจะมี 2 ตัว คือ

  • xdate : วันที่ที่ต้องการคำนวณ
  • th : ต้องการแสดงผลแบบปี พ.ศ หรือไม่ (1 = ใช่, 0 = ไม่)

ที่นี้มาลองทดสอบดู โดยการสร้างตารางเก็บวันที่กัน

DROP TABLE IF EXISTS DemoDate;
CREATE TABLE DemoDate (
    fielddate DATETIME NOT NULL
);
INSERT INTO DemoDate (fielddate) VALUES
    ('2008-09-01 00:00:00'),
    ('2008-04-04 00:00:00'),
    ('2009-05-25 00:00:00'),
    ('2010-06-30 00:00:00'),
    ('2011-07-01 00:00:00'), 
    ('2010-10-01 00:00:00'),
    ('2011-10-01 00:00:00'), 
    ('2012-09-30 00:00:00'), 
    ('2012-10-01 00:00:00'),
    ('2013-09-30 00:00:00'),
    ('2012-10-01 00:00:00'),
    ('2013-09-30 00:00:00'),
    ('2013-10-01 00:00:00'),
    ('2014-09-30 00:00:00'),
    ('2014-10-01 00:00:00'),
    ('2015-09-30 00:00:00'),
    ('2015-10-01 00:00:00'),
    ('2016-09-30 00:00:00'),
    ('2016-10-01 00:00:00'),
    (NOW()),
    ('0000-00-00 00:00:00');

แล้วก็มาทดสอบกัน

ขอให้มีความสุขกับการทำงานกัน แด่วันแรงานนนนนนน

**ช่วงนี้ไม่ค่อยได้เขียนบล็อคเลย แต่เขียน ๆ หน่อยเหอะ เดือนละเรื่องก็ยังดี T_T …
**งานช่วงนี้เหรอ ถามว่าท้อไหมตอบเลยว่ามากกกกก (แต่ไม่เคยถอยนะ หันหลังแม่มมเลย 555)

ไตรมาสใน MySQL แบบปีงบประมาณของไทย

ไตรมาส เป็นช่วงระยะเวลาสามเดือน ซึ่งแบ่งช่วงเวลา หนึ่งปี ออกเป็น สี่ ไตรมาส ในเชิงธุรกิจการพิจารณาผลประกอบการนิยมใช้ช่วงเวลาไตรมาส ในการประเมินผล กรณีที่เป็นตามปีปฏิทินจะแบ่งได้

  • ไตรมาสที่ 1 หมายถึงช่วงเดือนมกราคมถึงมีนาคม
  • ไตรมาสที่ 2 หมายถึงช่วงเดือนเมษายนถึงมิถุนายน
  • ไตรมาสที่ 3 หมายถึงช่วงเดือนกรกฎาคมถึงกันยายน
  • ไตรมาสที่ 4 หมายถึงช่วงเดือนตุลาคมถึงธันวาคม

แต่ระบบราชการของไทย ระบบรายงานส่วนใหญ่ขึ้นกับปีงบประมาณ ^_^

ปีงบประมาณ หรือ ปีงบการเงิน (อังกฤษ: fiscal year, financial year หรือ budget year) เป็นช่วงเวลาที่ใช้สำหรับคำนวณงบการเงินประจำปีในธุรกิจและองค์กรอื่น ๆ ในหลายเขตอำนาจตามกฎหมาย กฎข้อบังคับเกี่ยวกับการบัญชีและการเก็บภาษี จะต้องอาศัยรายงานเหล่านี้อย่างน้อยครั้งหนึ่งต่อสิบสองเดือน แต่ไม่จำเป็นว่าช่วงเวลาที่รายงานนี้จะต้องตรงกับปีตามปฏิทิน ซึงปีงบประมาณของไทยเริ่มตั้งแต่เดือนตุลาคมถึงเดือนกันยายนของปีถัดไป

ดังนั้นระบบไตรมาสจึงแบ่งออกเป็น

  • ไตรมาสที่ 1 หมายถึงช่วงเดือนตุลาคมถึงธันวาคม
  • ไตรมาสที่ 2 หมายถึงช่วงเดือนมกราคมถึงมีนาคม
  • ไตรมาสที่ 3 หมายถึงช่วงเดือนเมษายนถึงมิถุนายน
  • ไตรมาสที่ 4 หมายถึงช่วงเดือนกรกฎาคมถึงกันยายน

ซึ่งใน MySQL เองก็มีฟังก์ชั่นที่คำนวณหาไตรมาสชื่อ QUARTER อยู่แล้วซึ่งอิงจากปีปฏิทิน

QUARTER(date) : Returns the quarter of the year for date, in the range 1 to 4.

mysql> SELECT QUARTER('2016-10-18');
+-----------------------+
| QUARTER('2016-10-18') |
+-----------------------+
|                     4 | 
+-----------------------+

ผลอิงจากปีปฏิทินก็ตามนั้น ^_^ อ้าวว งั้นเรามาสร้างฟังก์ชั่นหาไตรมาสจากปีงบประมาณกัน

CREATE DEFINER=`root`@`localhost` FUNCTION `THQUARTER`(
    xdate DATETIME,
    th BIT) RETURNS int(11)
DETERMINISTIC
BEGIN
    DECLARE qt INT;
    
    SET qt = QUARTER(xdate) + th;
    
    RETURN IF(qt > 4, qt - 4, qt);
END

-- Test
mysql> SELECT THQUARTER('2016-10-18');
+-----------------------+
| THQUARTER('2016-10-18') |
+-----------------------+
|                     1 | 
+-----------------------+

 

มาลองเรียกใช้งานกัน สมมุติโจทย์ต้องการหารายงานการรับบริการของผู้ป่วยในสถานบริการแยกรายไตรมาส (ครั้ง)

-- Generate dummy data
CREATE TABLE `visit` (
  `visitno` mediumint(8) unsigned NOT NULL auto_increment,
  `visitdate` varchar(255),
  `pid` varchar(255) default NULL,
  `pcucode` varchar(255) default NULL,
  PRIMARY KEY (`visitno`)
) AUTO_INCREMENT=1;

INSERT INTO `visit` (`visitdate`,`pid`,`pcucode`) VALUES ("2017-01-09","5","yellow"),("2017-06-11","9","orange"),("2016-11-28","9","yellow"),("2017-06-02","2","red"),("2017-01-09","10","orange"),("2017-05-03","10","orange"),("2017-07-06","8","red"),("2017-06-25","10","yellow"),("2017-04-19","3","orange"),("2017-06-12","3","yellow");
INSERT INTO `visit` (`visitdate`,`pid`,`pcucode`) VALUES ("2016-11-12","10","orange"),("2017-06-18","5","red"),("2017-05-20","9","yellow"),("2017-04-01","2","red"),("2016-12-31","6","red"),("2017-02-05","8","orange"),("2017-02-19","3","red"),("2017-03-13","5","red"),("2017-03-27","3","yellow"),("2017-06-22","8","yellow");
INSERT INTO `visit` (`visitdate`,`pid`,`pcucode`) VALUES ("2017-01-17","6","red"),("2016-10-15","5","yellow"),("2017-05-30","8","orange"),("2017-04-29","5","red"),("2017-01-02","3","orange"),("2017-09-04","4","red"),("2017-01-09","3","orange"),("2016-12-15","7","yellow"),("2017-01-31","8","orange"),("2016-11-08","6","yellow");
INSERT INTO `visit` (`visitdate`,`pid`,`pcucode`) VALUES ("2017-01-10","5","orange"),("2016-11-20","3","yellow"),("2017-07-09","8","red"),("2017-01-20","8","red"),("2017-05-17","8","red"),("2017-08-05","5","yellow"),("2017-07-19","7","red"),("2017-05-06","10","yellow"),("2017-06-01","6","orange"),("2016-11-06","9","red");
INSERT INTO `visit` (`visitdate`,`pid`,`pcucode`) VALUES ("2017-09-20","5","orange"),("2017-01-28","8","yellow"),("2017-02-20","7","red"),("2016-11-24","5","orange"),("2016-12-27","5","orange"),("2017-05-20","6","yellow"),("2017-07-03","1","red"),("2017-09-09","8","yellow"),("2017-06-04","9","red"),("2017-03-04","9","orange");
INSERT INTO `visit` (`visitdate`,`pid`,`pcucode`) VALUES ("2017-09-12","6","orange"),("2017-07-24","1","yellow"),("2017-02-27","5","red"),("2017-08-21","3","yellow"),("2017-01-26","2","orange"),("2017-05-08","8","orange"),("2016-12-26","2","red"),("2017-06-24","7","red"),("2017-02-20","6","red"),("2017-04-18","10","yellow");
INSERT INTO `visit` (`visitdate`,`pid`,`pcucode`) VALUES ("2017-03-01","6","yellow"),("2017-07-15","1","yellow"),("2016-11-11","4","yellow"),("2017-06-27","10","orange"),("2017-01-02","10","orange"),("2017-05-08","7","orange"),("2017-03-16","2","red"),("2017-02-27","4","orange"),("2017-02-14","4","orange"),("2017-04-23","9","yellow");
INSERT INTO `visit` (`visitdate`,`pid`,`pcucode`) VALUES ("2016-12-02","1","orange"),("2017-04-15","9","yellow"),("2017-01-25","6","yellow"),("2017-05-06","7","yellow"),("2017-07-31","8","orange"),("2017-07-23","4","yellow"),("2017-06-02","7","red"),("2017-02-06","7","yellow"),("2017-02-14","6","red"),("2017-07-27","3","yellow");
INSERT INTO `visit` (`visitdate`,`pid`,`pcucode`) VALUES ("2016-10-21","1","red"),("2017-01-13","5","red"),("2017-06-06","1","red"),("2017-01-16","7","yellow"),("2017-01-29","9","orange"),("2016-11-06","7","red"),("2017-01-06","2","red"),("2017-01-12","6","yellow"),("2017-06-29","5","red"),("2017-04-04","10","yellow");
INSERT INTO `visit` (`visitdate`,`pid`,`pcucode`) VALUES ("2017-03-11","10","red"),("2017-05-22","2","red"),("2017-03-21","2","yellow"),("2017-02-19","3","orange"),("2016-11-30","3","red"),("2017-06-30","2","yellow"),("2017-09-17","2","red"),("2017-04-21","7","orange"),("2017-02-12","1","yellow"),("2017-05-12","7","red");

ผลลัพธ์

mysql> SELECT
    ->     pcucode,
    ->     SUM(IF(THQUARTER(visitdate, 1) = 1, 1, 0)) AS Q1,
    ->     SUM(IF(THQUARTER(visitdate, 1) = 2, 1, 0)) AS Q2,
    ->     SUM(IF(THQUARTER(visitdate, 1) = 3, 1, 0)) AS Q3,
    ->     SUM(IF(THQUARTER(visitdate, 1) = 4, 1, 0)) AS Q4,
    ->     COUNT(visitno) AS Total
    -> FROM visit
    -> GROUP BY pcucode
    -> WITH ROLLUP;
+---------+------+------+------+------+-------+
| pcucode | Q1   | Q2   | Q3   | Q4   | Total |
+---------+------+------+------+------+-------+
| orange  |    4 |   13 |    9 |    3 |    29 |
| red     |    6 |   12 |   12 |    6 |    36 |
| yellow  |    6 |   10 |   12 |    7 |    35 |
| NULL    |   16 |   35 |   33 |   16 |   100 |
+---------+------+------+------+------+-------+
4 rows in set (0.02 sec)

ปั่นรายงานกันต่อ T_T

 

 

Last record in each group

ใน MySQL กรณีเราต้องการหาค่าสูงสุด ตำสุด ในชุดข้อมูลนั้น ๆ จะหาได้จากการใช้ฟังก์ชั่น MIN() ซึ่งจะคืนค่าตำสุดและ MAX() จะคืนค่าสูงสุดในฟิลด์ที่ระบุ เช่น

SELECT MIN(column_name) FROM TABLE_NAME

กรณีที่หาค่าต่ำสุด/สูงสุด แยกตาม กลุ่มใด ๆ ก็ตามเพียงแค่ใช้ GROUP BY ต่อแค่นั้น

จบแล้วเหรอ เด๋วก่อนนนนนน !!! ชีวิตมันไม่ง่ายขนาดนั้น มันจะมีความต้องการอีกกรณีนึงคือ

อยากได้ค่า X ในเรคคอร์ดที่มีค่าสูงสุดในฟิลด์ที่ระบุ (Y) แต่ไม่ใช่ค่า Y นะ แยกตามกลุ่ม Z

ดูตัวอย่างข้อมูลดีกว่า

ค่า X คือ LABRESULT
ค่า Y คือ DATE_SERV
ค่า Z คือ CID

เพราะฉะนั้นผลลัพธ์ที่ได้ควรจะเป็นเช่นนี้ ที่เธอต้องการ

เราสามารถเขียนคำสั่งได้หลายแบบ อาทิ

แบบที่ 1

SELECT * FROM (
    SELECT HOSPCODE,CID,DATE_SERV,LABTEST,LABRESULT FROM demolasteachgroup ORDER BY DATE_SERV DESC
) t1 GROUP BY CID;

แบบที่ 2

SELECT *
FROM demolasteachgroup
WHERE DATE_SERV IN (
    SELECT MAX(DATE_SERV)
    FROM demolasteachgroup
    GROUP BY CID
);

แบบที่ 3

SELECT
    t1.*
FROM demolasteachgroup t1 
    LEFT JOIN demolasteachgroup t2 ON (t1.CID = t2.CID AND t1.DATE_SERV < t2.DATE_SERV)
WHERE t2.CID IS NULL;

ปล 1. จากการทดสอบพบว่า

MySQL Version แบบที่ 1 แบบที่ 2 แบบที่ 3
5.5
5.6
5.7 ×
10.2.2 (MariaDB) ×

√  ผลลัพธ์ถูกต้อง
× ผลลัพธ์ผิด

ปล. 2 ตัดเงื่อนไขเรื่อง Big O นะ มองถึงผลลัพธ์ที่ถูกต้องอย่างเดียว

ปล. 3 มีประเด็นสงสัยจากเพื่อนในวงการ(สุขภาพ) ถามมาที่จับใจความได้ก็ (ถ้ามีเพิ่มเติมก็ discuss กันได้นะครับ ยินดี)
Q : ยกตัวอย่างที่เป็นรูปธรรมเห็นได้หน่อยที่บอกว่าความต้องการอีกกรณีนึง
A : เช่น ต้องการหาค่าน้ำตาลล่าสุดxxของผู้ป่วยหรือผลแลป HbA1C ล่าสุดของผู้ป่วย เป็นต้น กรณีหากได้ค่าที่ผิดพลาดออกมามีผลอย่างมาก เพราะ 2 รายการข้างต้นเป็นหนึ่งในเงื่อนไขที่บอกถึงการควบคุมน้ำตาลได้ดีของผู้ป่วย ซึ่งอยู่ใน KPI ทุก ๆ ปีของคนทำงานด้านสุขภาพ (คนไทยเป็นเบาหวานเยอะมากนะ อันนี้เป็นเรื่องน่ากังวลเหมือนกัน) KPI เกือบผ่านหรือเกือบไม่ผ่านความรุนแรงในการตำหนิต่างกันเยอะ ^_^

Q : ทดสอบกับ MySQL คนละ Version ให้ผลไม่เหมือนกัน อะไร ยังไง
A : ที่ให้ผลลัพธ์ไม่ถูกต้องนั้น เฉพาะแบบที่ 1 นะ ตามปล. 1 คือตัวนี้

SELECT * FROM (
    SELECT HOSPCODE,CID,DATE_SERV,LABTEST,LABRESULT FROM demolasteachgroup ORDER BY DATE_SERV DESC
) t1 GROUP BY CID;

ดูรูปหล่ะกัน เราจัดเรียงข้อมูลตามวันที่เพื่อหาล่าสุด กวาด ๆ ด้วยตาจะเห็นว่ากรอบสีแดงคือเรคคอร์ดที่ถูกต้อง ที่คำสั่ง SQL ควรจะคืนผลลัพธ์มา

แต่ผลลัพธ์จะผิดทันทีถ้าใช้ MySQL Version 5.7 เป็นต้นไป (ปัจจุบันเวอร์ชั่น 5.7.17)

** ไม่ได้หาสาเหตุนะว่าผิดเพราะอะไร ใครจะลองไปทดสอบเวอร์ชั่นอื่น ๆ คำสั่งที่ใช้ทดสอบก็ตามนี้
MySQL 5.5 – http://sqlfiddle.com/#!2/38ef1b/2
MySQL 5.6 – http://sqlfiddle.com/#!9/38ef1b/4
MySQL 5.7 – http://rextester.com/JALDD35756

MySQL (Simple)Mask Function

ถ้าวันนึงเกิดจำเป็นจริง ๆ ต้องจัดรูปแบบการแสดงผลข้อมูลในฐานข้อมูลขึ้นมาเช่น หมายเลขโทรศัพท์ เลขประจำตัวประชาชน หรือจัดรูปแบบตัวเลขในแบบอื่น ๆ โดยปกติแล้ว MySQL มีฟังก์ชั่นที่เกี่ยวข้องกับรูปแบบการแสดงผลอยู่ไม่กี่ตัว เช่นพวกตัวเลข(เงิน) วันที่ ซึ่งก็มีแค่นั้นแหล่ะ ^_^

** ส่วนตัวแล้วไม่แนะนำให้ใช้ (แล้วเขียนขึ้นมาทำไมฟระ 5555) คือถ้าจะใช้ก็มีให้ใช้ได้แต่ไม่แนะนำไง เป็นภาระการประมวลผลโดยใช่เหตุ ปล่อยให้เป็นหน้าที่ของฟรอนท์ไปหล่ะกัน
DELIMITER $$
DROP FUNCTION IF EXISTS SIMPLEMASK$$

CREATE FUNCTION SIMPLEMASK (
    xvalue VARCHAR(32), 
    xformat VARCHAR(32)
)
RETURNS CHAR(32) 
DETERMINISTIC
BEGIN

    DECLARE input_len TINYINT;
    DECLARE tc CHAR;
    DECLARE idx TINYINT;
    DECLARE yformat VARCHAR(32);
    DECLARE posinsert TINYINT;
    DECLARE newstring VARCHAR(32);
    
    # Initialize variables
    SET yformat = REPLACE(xformat, '#', '');
    SET input_len = LENGTH(yformat);
    SET idx = 1;
    SET posinsert = 0;
    
    # Construct formated string
    WHILE ( idx <= input_len ) DO
        SET tc = SUBSTR(yformat, idx, 1);
        SET posinsert = LOCATE(tc, xformat, (idx + posinsert));
        SET newstring = CONCAT(tc, SUBSTR(xvalue, posinsert, 1));
        SET xvalue = INSERT(xvalue, posinsert, 1, newstring);
        SET idx = idx + 1;
    END WHILE;
    
    RETURN xvalue;
    
END $$

DELIMITER ;

-- Test
SELECT SIMPLEMASK(1234567890123,'#-####-#####-##-#'); -- CID/1-2345-67890-12-3

ป.ล.

อ้ายผิดเอง ทีดูแลเจ้าบ่ดี…

 

กู่แคน School - เจ็บเติบนึง
คำร้อง/ ทำนอง ก้องศิลป์ ฟ้าล่วงบน
เรียบเรียบ กู่แคน School

อ้ายผิดเอง ทีดูแลเจ้าบ่ดี
ฮักเฮาบัดนี้ถึงที่อวสาน
ปานนั้นบ้อหัวใจเอ๋ย ใจที่เคยให้ความหวัง
มันคงบ่ยังแล้ว มันคงบ่เหลือแล้ว
เบิ๊ดคักเบิ๊ดแน่ เบิ๊ดจนบ่มี

กะพาหัวใจ ที่ฮักเจ้าไปกับความหวัง
อ้ายกะไปฮอดฝั่งแต่มันช้าเกินไป
ถามว่ามาหยังตอนนี้
คนดีเอ๊ย ข่อยหนิฮักเจ้าหลาย
มาแสดงความฮักเป็นเทื่อสุดท้าย
ก่อนสิกายเป็นแค่ ควมเก่า
อ้ายคงต้องเศร้า ต้องเหงาหลาย

กะคงซำตาย ทั้งเป็น ที่เจ้าบอกว่าบ่ได้ฮักกัน
มันจบลงแล้วหนอความสัมพันธ์
หัวใจมันกลั้น น้ำตาสิไหล
ใจเอ๋ยพออยากแลนไปกอด
ฮักเจ้าตลอด บ่อยากเสียเจ้าไป
สุดท้ายสองเฮากะคงต้องน้ำตาไหล
ฮ้องไห้ใส่กัน

ถามว่ามาหยังตอนนี้
คนดีเอ๊ย ข่อยหนิฮักเจ้าหลาย
มาแสดงความฮักเป็นเทื่อสุดท้าย
ก่อนสิกายเป็นแค่ ควมเก่า
อ้ายคงต้องเศร้า ต้องเหงาหลาย

กะคงซำตาย ทั้งเป็น ที่เจ้าบอกว่าบ่ได้ฮักกัน
มันจบลงแล้วหนอความสัมพันธ์
หัวใจมันกลั้น น้ำตาสิไหล
ใจเอ๋ยพออยากแลนไปกอด
ฮักเจ้าตลอด บ่อยากเสียเจ้าไป
สุดท้ายสองเฮากะคงต้องน้ำตาไหล
ฮ้องไห้ใส่กันก่อนเฮาสิจากหนี

สุดท้ายสองเฮากะคงต้องน้ำตาไหล
ฮ้องไห้ใส่กัน

 

Find and log which top 5 processes are taking high cpu

เวลาคอมพิวเตอร์ตระกูล *nix พบปัญหา อันดับแรก ๆ ที่จะเริ่มทำเพื่อแก้ปัญหาและช่วยชีวิตเราก็คือเปิด Log เกิดปัญหาปุ๊บเปิด Log ก่อนเลยแต่บางกรณีเราก็มอนิเตอร์ผ่านโปรแกรม/คำสั่งตัวอื่น โดยทั่ว ๆ ไปมักจะใช้ top เพื่อมอนิเตอร์การทำงานของคอมพิวเตอร์ ซึงโปรแกรมจะแสดงสถานะของ Memory, CPU, Process Terminal_042

top นี่คือต้องมีเวลานั่งดูเพราะผลลัพธ์ที่ได้จะแสดงออกมาแบบเรียลไทม์ อีกทางเลือกหนึ่งก็คือใช้คำสั่ง ps

ps – report a snapshot of the current processes.

 a@b  ~  ps -aux                                    1 ↵  481  11:31:05 
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0 185556  6264 ?        Ss   09:55   0:02 /sbin/init spla
root         2  0.0  0.0      0     0 ?        S    09:55   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    09:55   0:00 [ksoftirqd/0]
root         5  0.0  0.0      0     0 ?        S<   09:55   0:00 [kworker/0:0H]
root         7  0.0  0.0      0     0 ?        S    09:55   0:05 [rcu_sched]
root         8  0.0  0.0      0     0 ?        S    09:55   0:00 [rcu_bh]
root         9  0.0  0.0      0     0 ?        S    09:55   0:00 [migration/0]
root        10  0.0  0.0      0     0 ?        S    09:55   0:00 [watchdog/0]
root        11  0.0  0.0      0     0 ?        S    09:55   0:00 [watchdog/1]

ps ใช้แล้วก็จบไง จะดูอีกก็สั่งอีก (ใช้ watch ดูแบบ top ก็ได้นะ แต่จะใช้ watch ก็ไปใช้ top ละเอียดกว่าเยอะ) แต่ในกรณีที่ต้องการเก็บ Log ผลลัพธ์ที่ได้จาก ps เพื่อดูการทำงาน เช่นอาจจะต้องการมอนิเตอร์โปรเสสที่ใช้งานสูง ๆ หรือมอนิเตอร์ดูภายหลังว่าใครกำลังแอบแดกเมมมหาโหด ก็ทำแบบนี้ได้

while true; do 
    ps auxf | sort -nrk 3,3 | head -n 5 >> log.log; 
    sleep 1; 
done

ผลลัพธ์ที่ได้

a@b  ~  tail -f log.log                              ✓  488  11:40:13 
a        6019 28.6  4.0 2189732 663568 tty2   Sl+  09:57  28:48 /usr/lib/firefox/firefox
a        4376  4.7  1.2 2334564 198912 tty2   Sl+  09:57   4:49              \_ /usr/bin/gnome-shell
root      4222  2.7  0.4 534160 79804 tty2     Sl+  09:57   2:43          \_ /usr/lib/xorg/Xorg vt2 -displayfd 3 -auth /run/user/1000/gdm/Xauthority -background none -noreset -keeptty -verbose 3

 

 

มาใช้ zsh กัน มัน Cool กว่าเยอะ

เดิมปกติ bash shell ซึ่งเป็น shell มาตรฐานของ Ubuntu ก็เพียงพอต่อการใช้งานในระดับนึงแล้วหล่ะ แต่ไม่เคยมีอะไรพอดี ^_^ zsh ช่วยให้อะไรหลายอย่างง่ายขึ้น เช่น ช่วยเพิ่ม Productivity ให้ developer noob ส่วน feature เด่น ๆ ของ zsh คร่าว ๆ ก็มี

  • Autocompleted
  • ตรวจคำสั่งที่พิมพ์ผิด (ก็ไม่ทุกคำสั่งหรอก)
  • รองรับ Right-hand prompt
  • Plugin/Module เด่น ๆ ก็มี Oh my zsh และ Prezto

เริ่มก็ลง zsh กันซะ

sudo apt install zsh

ต่อมาก็เปลี่ยนเข้าใช้ zsh เป็นค่าเริ่มต้นเมื่อเปิด Terminal โดยใช้คำสั่ง chsh

a@b:~$ chsh
Password: 
Changing the login shell for a
Enter the new value, or press ENTER for the default
  Login Shell [/bin/bash]: /bin/zsh

แล้วก็ใช้ path ของ zsh ไปแทน bash shell แล้วก็ login เข้าใหม่ไป 1 ที

ทีนี้อย่างอื่นก็ได้หมดละ ต่อไปก็เพิ่ม Module ให้ zsh เป็นสเต็ปต่อไป อย่างที่บอกคือมันมีเด่น ๆ อยู่ 2 ตัวคือ Oh My zsh และ Prezto

  • Oh my zsh (http://ohmyz.sh/) เป็น configuration framework ที่รวบรวม plugin และ theme สำหรับ zsh เพื่อให้ใช้งานได้อย่างมีประสิทธิภาพยิ่งขึ้น โดยจะรวบรวม plugin สำหรับโปรแกรมหลาย ๆ ตัวที่มักใช้กันบ่อย ๆ พวก git, vagrant, composer, rails, docker อื่น ๆ อีก
  • Prezto (https://github.com/sorin-ionescu/prezto) เป็น configuration framework ของ zsh เช่นเดียวกับ oh-my-zsh เริ่มเดิมทีนั้น Prezto นั้นเป็น fork ของ oh-my-zsh แต่เนื่องจากแนวคิดไปคนละทางกับ oh-my-zsh เลยถูก rewrite ใหม่ ทำให้เราเพิ่มความสามารถหรือลูกเล่นให้กับ zsh ได้มากเดิม ไม่ว่าจะเป็น theme หรือ plugin (ใน Prezto จะเรียกว่า module) ซึ่งดูแล้วส่วนมากจะเป็นพวก alias ซะมากกว่า

เราเลือก Prezto นะ ^_^ วิธีใช้/ติดตั้ง ก็มีคนเขียนเอาไว้ดีมาก (ขี้เกียจเขียนต่อ 555) ตามนี ลองใช้ Prezto กับ zsh (https://armno.github.io/2015/03/24/oh-my-zsh-to-prezto)

ปล. ส่วน Theme เราก็ชอบ Theme powerlevel9k (https://github.com/bhilburn/powerlevel9k)powerlevel9k