Coffee & Code: สร้างฐานข้อมูลคาเฟ่พร้อมหา insight ช่วยธุรกิจ

ในธุรกิจหลายๆเจ้าไม่ว่าจะเป็นร้านอาหาร, ร้านกาแฟ, retail หรือจะเป็นบริษัทต่างๆที่มีพนักงาน มี product/service ที่ต้องขายให้กับลูกค้า เกือบจะทุกวงการจะต้องมีการเก็บข้อมูลทุกอย่างเอาไว้เพื่อเป็นหลักฐาน

ประเด็นคือเราเคยจัดการกับข้อมูลเหล่านี้ให้เป็นระเบียบและเป็นระบบหรือเปล่า มีข้อมูลเยอะแต่เคยเอาข้อมูลเหล่านั้นมาวิเคราะห์เพื่อสร้าง value ให้กับธุรกิจเราต่อมั้ย

สำหรับธุรกิจขนาดเล็กอาจจะไม่จำเป็นต้องทำฐานข้อมูล (database) ก็ได้ แต่ในธุรกิจขนาดกลางจนถึงขนาดใหญ่น่าจะต้องมีอย่างแน่นอน

ถ้าธุรกิจไม่ว่าจะขนาดไหนหากไม่มี database ก็เหมือนไม่มี resource ที่จะอาศัยอยู่ได้หรืออยู่ได้แบบลำบาก

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

ดังนั้น วันนี้เราจะมาให้ทุกคนเห็นวิธีสร้าง/จัดการ/วิเคราะห์ database อย่างง่ายกัน เพื่อที่ทุกคนจะสามารถไปปรับใช้กับธุรกิจหรือชีวิตของตัวเองได้

  1. ออกแบบ database ให้ดี
  2. สร้างไฟล์ database
  3. ทำความรู้จักกับ SQL
  4. สร้าง table เพื่อเก็บ data
    1. สร้าง table สำหรับเก็บข้อมูล
    2. Modify กับ table ที่เรามีง่ายๆด้วย ALTER
    3. Insert ข้อมูลลง database
    4. Update ข้อมูลเพิ่มเติม
    5. Delete data ที่เราไม่ต้องการ
    6. Delete table ที่เราไม่ต้องการ
  5. เจาะ data หา insights!
    1. การ join tables โดยใช้ WHERE clause
    2. Subqueries
    3. Common Table Expression (CTEs)
  6. More posts

ออกแบบ database ให้ดี

การออกแบบ database ให้ดีก็เหมือนออกแบบบ้านให้ดีซักหลังนึง เราอยากจะมีบ้านที่มีโครงสร้างแข็งแรง อยู่กับเราได้นานๆไม่ว่าจะเจอสภาพอากาศแบบไหนก็ทนได้

***เราก็ต้องเข้าใจก่อนด้วยว่าผู้ที่จะเข้ามาอาศัยในบ้านหลังนี้เป็นคนแบบไหน daily routine เป็นอย่างไร เพื่อให้การออกแบบตอบโจทย์ลูกบ้านด้วย

ดังนั้น สิ่งสำคัญเป็นอันดับแรกเลยคือ ทำความเข้าใจธุรกิจของตัวเองซะก่อนว่า ภายในธุรกิจเรามีโครงสร้างและการทำงานภายในและภายนอกองค์กรเป็นอย่างไร

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

ในบทความนี้เราลองสร้าง 4 tables เพื่อให้เห็นภาพ ยิ่งธุรกิจเราใหญ่มีความซับซ้อนมาก จำนวน tables ก็เยอะตามไปด้วยนะ

  • menus เพราะลูกค้ามาร้านเราก็อยากมาสั่งเครื่องดื่ม ขนมใช่มั้ย เป็น table ที่ขาดไม่ได้เลย
  • staffs ร้านจะขาดพนักงานไม่ได้เลย ไม่อย่างนั้นใครจะเป็นช่วยรันงานในร้านให้เรา ;-;
  • customers และร้านจะขาดลูกค้าไม่ได้เช่นกัน ลูกค้าคือพระเจ้า กำไรธุรกิจจะมากหรือน้อยก็ขึ้นอยู่กับตัวแปรนี้เลย
  • transactions สิ่งที่เก็บข้อมูลระหว่างลูกค้า รายการที่ลูกค้าสั่ง และพนักงานที่รับผิดชอบ ก็คือ บิล/ใบเสร็จที่จะเป็นหลักฐานให้เราเช็คย้อนหลังได้

แล้วทุกคนล่ะ คิดว่าในธุรกิจเกี่ยวกับคาเฟ่ ร้านกาแฟควรมี table อะไรเพิ่มเติมอีกนะ

โดยสิ่งที่ช่วยให้เราเห็นภาพรวมของ database เราได้ดีขึ้น นั่นคือ ER diagram ย่อมาจาก Etity-Relationship diagram

  • Etity ก็หมายถึง table ทั้งหมดใน database
  • Relationship ก็คือ ความสัมพันธ์ระหว่าง table หนึ่งกับ table หนึ่ง ซึ่งความสัมพันธ์ก็มีหลายแบบ โดยส่วนใหญ่จะเป็นแบบ one-to-many

ER diagram แสดงความสัมพันธ์สำหรับทุก table ในไฟล์ my_cafe.db

Note: แต่ละ table ควรจะมีหนึ่งคอลัมน์เป็น id ของ table นั้นๆสำหรับการ join tables เข้าด้วยกัน

ทุกคนสามารถลองออกแบบ database ของตัวเองได้ง่ายๆที่ dbdiagram.io บนเว็บ browser ฟรีๆ ใช้งานง่าย ทำเสร็จโหลดออกมาเป็นไฟล์ .pdf หรือ .png ไปใช้งานต่อได้เลย


สร้างไฟล์ database

เราจะสร้าง database ผ่านเว็บ browser ที่มีชื่อว่า replit.com กัน ใช้งานฟรีด้วย (แต่สร้างได้แค่ 3 projects น้า)

สมัคร account เสร็จแล้ว กด Create Repl แล้วเลือก SQLite ได้เลย

Keyword ที่ใช้ในการสร้างไฟล์ database คือ .open แล้วตามด้วยชื่อไฟล์ โดยนามสกุลไฟล์เป็น .db เช่น

.open ports_coffee.db

หรือใครอยากจะลองติดตั้ง software ลง local computer / laptop เป็นของตัวเอง เราขอแนะนำเป็น DB Browser for SQLite โหลดใช้ได้ฟรีทั้ง Windows / macOS เลย


ทำความรู้จักกับ SQL

SQL ย่อมาจาก Structured Query Language เป็นภาษาที่เราใช้สำหรับสื่อสารระหว่างเรากับ database เพื่อจัดการและดึงข้อมูลที่เราต้องการออกมาจาก database

โดย SQL จะมีอยู่หลายแบบ ไม่ว่าจะเป็น SQLite, MySQL, PostgreSQL, Microsoft SQL Server เป็นต้น โดยตัวที่เราเลือกจะเป็น SQLite ซึ่งเป็น standard SQL เหมาะสำหรับผู้เริ่มต้นเรียนภาษา SQL


สร้าง table เพื่อเก็บ data

สร้าง table สำหรับเก็บข้อมูล

ถ้า เราบอกว่า database เปรียบเสมือนบ้าน 1 หลัง แล้ว table กับ data ก็เป็นเหมือนห้องต่างๆภายในบ้าน และ เฟอร์นิเจอร์ในแต่ละห้องที่ถูก partition แล้วนั่นเอง

ดังนั้น database หลังนี้จะดีหรือไม่ดีก็ขึ้นอยู่กับการวางแผนของเราด้วย ก็เหมือนกับบ้านของเรา ถ้าแบ่งสัดส่วนแต่ละห้องได้เหมาะสมและเลือกเฟอร์นิเจอร์ได้ดี บ้านเราก็น่าอยู่ ใช้งานได้ไปอีกนาน

โดย syntax ในการสร้าง table เราจะใช้ keyword ดังนี้

CREATE TABLE table_name (
   column_name1 data_type,
   column_name2 data_type,
   .
   .
   .
);

Data type ที่เราใช้กันเป็นส่วนใหญ่ ได้แก่

  • int คือ จำนวนเต็ม (Integer)
  • real / float คือ จำนวนที่สามารถมีทศนิยมได้ ในทางคณิตศาสตร์ คือ Real Number
  • text / varchar คือ ข้อความซึ่งอยู่ภายใต้เครื่องหมาย double quote (“…….”)
  • date / datetime คือ วันและเวลา
-- create table
CREATE TABLE menus (
  menu_id int PRIMARY KEY,
  name text,
  price real,
  category text
);

CREATE TABLE staffs (
  staff_id int PRIMARY KEY,
  name text,
  position text
);

CREATE TABLE customers (
  customer_id int PRIMARY KEY,
  name text
);

CREATE TABLE transactions (
  transaction_id int PRIMARY KEY,
  customer_id int,
  staff_id int,
  menu_id int,
  quantity int,
  invoicedate date 
);

Modify กับ table ที่เรามีง่ายๆด้วย ALTER

ALTER เป็น keyword ที่ใช้สำหรับปรับแต่ง table ได้ เช่น add new columns, rename tables, rename columns

1. เพิ่มคอลัมน์ใหม่ใน table ที่มีอยู่

Syntax ในการ add new columns

ALTER TABLE table_name
ADD column_name_to_added data_type;

ตัวอย่างการใช้งาน เช่น เราอยากจะเพิ่ม column hiredate ลงไปใน table staffs

ALTER TABLE staffs
ADD hiredate date;

2. เปลี่ยนชื่อ table ที่มีอยู่

Syntax ในการ rename tables

ALTER TABLE old_table_name
RENAME TO new_table_name;

ตัวอย่างการใช้งาน เช่น เราอยากเปลี่ยนชื่อ table customers เป็น employees

ALTER TABLE customers
RENAME TO employees;

3. เปลี่ยนชื่อคอลัมน์ที่มีอยู่

Syntax ในการ rename columns

ALTER TABLE table_name
RENAME old_column_name TO new_column_name;

ตัวอย่างการใช้งาน เช่น เราอยากเปลี่ยนชื่อ column name ใน table customers เป็น nickname

ALTER TABLE customers
RENAME name TO nickname;

Insert ข้อมูลลง database

ขั้นต่อไป ถ้าสร้างบ้าน แบ่งห้องแล้ว แต่ไม่มีเฟอร์นิเจอร์ก็อยู่ไม่ได้สิใช่มั้ย
ดังนั้น เราจะมาใส่ data ลงไปในแต่ละ table กัน โดยการใช้คำว่า INSERT INTO กัน

Syntax ในการเพิ่มข้อมูลลง table

INSERT INTO table_name VALUES 
(row1_value1, row1_value2, ...),
(row2_value1, row2_value2, ...),
.
.
.

ตัวอย่างการเพิ่มข้อมูลเมนูทั้งหมดในคาเฟ่ของเรา

-- insert data
INSERT INTO menus VALUES 
  (1,'Single Espresso',60,'coffee'),
  (2,'Double Espresso',70,'coffee'),
  (3,'Hot Americano',80,'coffee'),
  (4,'Iced Americano',90,'coffee'),
  (5,'Hot Latte',90,'coffee'),
  (6,'Iced Latte',100,'coffee'),
  (7,'Hot Cappuccino',90,'coffee'),
  (8,'Iced Cappuccino',100,'coffee'),
  (9,'Hot Mocha',100,'coffee'),
  (10,'Iced Mocha',110,'coffee'),
  (11,'Hot Caramel Macchiato',100,'coffee'),
  (12,'Iced Caramel Macchiato',110,'coffee'),
  (13,'Thai Milk Tea',90,'non_coffee'),
  (14,'Matcha Latte',100,'non_coffee'),
  (15,'Hojicha Latte',100,'non_coffee'),
  (16,'Dark Chocolate',100,'non_coffee'),
  (17,'Yuzulemonade Sparkling',100,'non_coffee'),
  (18,'Honey Lemon Tea',100,'non_coffee'),
  (19,'Honey Lemon Sparkling',100,'non_coffee'),
  (20,'Dirty',110,'special_drink'),
  (21,'Orangano',100,'special_drink'),
  (22,'Dalgona Latte',120,'special_drink'),
  (23,'Sesame Latte',120,'special_drink'),
  (24,'Einspanner',120,'special_drink'),
  (25,'Canele',75,'dessert'),
  (26,'Butter Croissant',80,'dessert'),
  (27,'Butter Chocolate Croissant',95,'dessert'),
  (28,'Croffle',85,'dessert'),
  (29,'Lemon Cake',95,'dessert'),
  (30,'Choc Chip Cookie',85,'dessert'),
  (31,'Pain Aux Raisin',95,'dessert'),
  (32,'Pain Aux Chocolate',95,'dessert');

ตัวอย่างการเพิ่มข้อมูลพนักงานทุกคนในคาเฟ่

INSERT INTO staffs VALUES 
  (1,'Pon','CEO'),
  (2,'James','Manager'),
  (3,'Tuanote','Senior Barista'), 
  (4,'Ice','Senior Barista'),
  (5,'Bee','Accounting'),
  (6,'Fern','RD'),
  (7,'Nut','Marketing'),
  (8,'Ling','HR');

ตัวอย่างการเพิ่มข้อมูลลูกค้าทุกคนในคาเฟ่

INSERT INTO customers VALUES
  (1,'Tan'),
  (2,'Peach'),
  (3,'Jane'),
  (4,'Dith'),
  (5,'Kao'),
  (6,'Wa'),
  (7,'Tee'),
  (8,'Pan'),
  (9,'New'),
  (10,'Toey'),
  (11,'Fai'),
  (12,'Dew'),
  (13,'Boss'),
  (14,'Ta');

ตัวอย่างการเพิ่มข้อมูลรายการสั่งซื้อทุกรายการในคาเฟ่

INSERT INTO transactions VALUES
  (1,9,5,10,1,'2024-06-22'),
  (2,10,2,15,3,'2024-06-22'),
  (3,4,4,28,1,'2024-06-22'),
  (4,2,4,13,3,'2024-06-22'),
  (5,13,5,11,1,'2024-06-22'),
  (6,8,4,5,1,'2024-06-22'),
  (7,8,5,12,1,'2024-06-23'),
  (8,8,4,24,2,'2024-06-23'),
  (9,3,4,32,3,'2024-06-23'),
  (10,1,4,4,2,'2024-06-23'),
  (11,2,5,27,1,'2024-06-23'),
  (12,3,4,20,2,'2024-06-24'),
  (13,7,2,17,1,'2024-06-24'),
  (14,13,3,30,1,'2024-06-24'),
  (15,8,2,9,1,'2024-06-24'),
  (16,13,4,27,3,'2024-06-25'),
  (17,8,4,12,2,'2024-06-25'),
  (18,1,2,12,1,'2024-06-25'),
  (19,1,3,14,1,'2024-06-27'),
  (20,5,4,19,3,'2024-06-28'),
  (21,9,2,1,1,'2024-06-28'),
  (22,14,1,26,2,'2024-06-28'),
  (23,14,4,3,1,'2024-06-29'),
  (24,4,4,5,3,'2024-06-29'),
  (25,12,4,20,3,'2024-06-29'),
  (26,12,1,26,3,'2024-06-29'),
  (27,6,3,21,3,'2024-06-29'),
  (28,7,2,21,1,'2024-06-30'),
  (29,2,1,19,1,'2024-06-30'),
  (30,14,4,22,1,'2024-06-30');

หากต้องการแก้ไขข้อมูลหลังจากขั้นตอนนี้ ให้ใช้ keyword ในหัวข้อถัดไป

Update ข้อมูลเพิ่มเติม

ในบางครั้ง เราก็อาจจะใส่ข้อมูลผิด เช่น พิมพ์ชื่อพนักงานผิดไปตัวอักษรนึง กรอกราคาสินค้าผิด ทุกอย่างล้วนเกิดขึ้นได้จาก human error

Syntax ในการ update data ใน table

UPDATE table_name
SET column_name1 = value1, column_name2 = value2
WHERE condition;

เช่น เราต้องการเปลี่ยนชื่อเมนูจาก Hot Latte เป็น Hot Caffe Latte ซึ่งเป็นข้อมูลจาก table menus ที่มี menu_id = 5 พร้อมปรับขึ้นราคาจาก 90 บาทเป็น 95 บาท

UPDATE menus
SET name = "Hot Caffe Latte", price = 95
WHERE menu_id = 5;

Delete data ที่เราไม่ต้องการ

Syntax ในการลบข้อมูลออกจาก table

DELETE FROM table_name WHERE condition;

เช่น ณ วันนี้มีพนักงานคนหนึ่งที่ชื่อ Fern แผนก RD ลาออก เราเลยต้องนำข้อมูลของพนักงานคนนี้ออกจาก table staffs

DELETE FROM staffs WHERE name = "Fern"

Delete table ที่เราไม่ต้องการ

สร้าง table ได้ ก็ต้องลบได้ บางครั้งเราอาจจะเผลอสร้าง table นั้นขึ้นมาโดยไม่ได้ตั้งใจ ดังนั้น เราจึงขอแนะนำวิธีการลบ table ที่ easy มากๆแค่ keyword เดียวเลย นั่นคือ

DROP TABLE table_name;

ตัวอย่างเช่น เราจะสร้าง table ที่ชื่อว่า branch ไปใส่ใน database เฉยเลย ทั้งที่จริงคาเฟ่เรามีแค่สาขาเดียว ร้องไห้แล้ว ;-;

CREATE TABLE branches (
  branch_id int PRIMARY KEY,
  name text,
  address text,
  street text,
  sub_district text,
  district text,
  province text,
  country text,
  latitude real,
  longitude real
);
DROP TABLE branches

เห็นมั้ยว่าง่ายนิดเดียวเอง หมายถึง ทิ้งของที่เค้าให้มาง่าย แต่สร้างความสัมพันธ์ให้เค้ากลับมาหาอะยาก เดี๋ยวๆๆๆๆเริ่มออกทะเลไปไกลละ ;-;


เจาะ data หา insights!

เมื่อเรามีบ้านที่มั่นคงแข็งแรง มีห้องและเฟอร์นิเจอร์ต่างๆพร้อมใช้งานกันแล้ว หลังจากนี้ก็ถึงเวลาสร้างครอบครัวที่มีความสุขและอบอุ่นกันแล้ว นั่นก็คือ การสร้าง value กลับมาให้ธุรกิจของเรา โดยการหา insight จาก data นั่นเอง

และ insight ที่ดี มักเริ่มต้นจากการตั้งคำถามที่ดี โดยเทคนิคที่เราจะใช้หา insight กันในครั้งนี้ เราจะใช้อยู่ด้วยกัน 3 เทคนิคด้วยกัน

การ join tables โดยใช้ WHERE clause

โดยปกติการ join tables ใน SQL เราจะใช้คำว่า JOIN ON เป็นหลัก ตัวอย่างเช่น

SELECT * FROM customers AS cu 
JOIN transactions AS tr
ON cu.customer_id = tr.customer_id

แต่เราสามารถปรับ syntax ด้านบนมาเป็นตัวอย่าง code ด้านล่างได้

SELECT * 
FROM customers AS cu,
     transactions AS tr
WHERE cu.customer_id = tr.customer_id

Code ของเราสั้นลงเยอะเลย แถมได้ result เหมือนกันเป๊ะ!
ต่อจากนี้เดี๋ยวเรามาหา insight จาก data ที่เรา mock up ไว้แล้วด้วยวิธีนี้กัน

1. เมนูที่ขายดีที่สุด 3 อันดับแรกของคาเฟ่นี้

สิ่งที่เราอยากจะได้ใน query result นี้คือ ชื่อเมนู (menus.name) และ ยอดขายรวมทั้งหมดในแต่ละเมนู

แต่เนื่องจาก ยอดขายทั้งหมด (total sales) จะเกิดจากผลรวม (SUM) ของราคาขาย (menus.price) x จำนวนที่ขายได้ (transactions.quantity)

ทำให้เราต้อง join table menus กับ table transaction ด้วยคีย์ที่เป็น menu_id นั่นเอง และจับกลุ่มยอดขายตามชื่อเมนู เรียงข้อมูลจากมากไปน้อยตามยอดขาย

-- Top 3 Most Popular Menus at the cafe
  
SELECT 
  me.name AS Menu_Name,
  SUM(me.price * tr.quantity) AS Total_Sale
FROM menus AS me, 
     transactions AS tr
WHERE tr.menu_id = me.menu_id
GROUP BY 1
ORDER BY 2 DESC
LIMIT 3;

จาก result ที่ได้ จะเห็นว่า Dirty ขายดีที่สุด รองลงมา คือ Iced Caramel Macchiato และ Orangano (iced americano + orange juice)

2. วันไหนในเดือนมิถุนายน 2024 ที่มียอดขายต่ำที่สุด

Case นี้จะคล้ายๆกับการ query ก่อนหน้านี้เลย แต่เปลี่ยนการจับกลุ่มตามชื่อเมนูเป็นวันที่ในเดือนมิถุนายน 2024 และเรียงยอดขายจากน้อยไปมาก

ใน query นี้จะมีฟังก์ชันที่ใช้ดึงค่าต่างๆกับข้อมูลที่เป็น date ด้วย นั่นคือ STRFTIME()

-- Which day in June 2024 had the lowest sales?

SELECT
  STRFTIME('%d', invoicedate) AS Day_of_June_2024,
  SUM(price * quantity) AS Total_Sale
FROM transactions AS tr, menus AS me
WHERE tr.menu_id = me.menu_id
GROUP BY 1
ORDER BY 2;

จาก result จะเห็นว่า วันที่ขายได้น้อยที่สุดของเดือนมิถุนายน คือ วันที่ 27 รองลงมา คือ วันที่ 30 และวันที่ 24

3. พนักงานที่ทำยอดขายได้มากที่สุดในช่วงวันที่ 22-30 มิถุนายน 2024

สังเกตว่า สำหรับการ query ใน case นี้ สิ่งที่ต้องเปลี่ยนจาก query เดิมคือ ชื่อพนักงาน (staffs.name) และต้องจับกลุ่มตามพนักงานแต่ละคน

ทำให้การ query รอบนี้ต้อง join 3 tables พร้อมกัน โดยใช้คีย์ staff_id เพิ่มเข้าไปจากเดิม (ถ้าเขียน JOIN ON ปกติ code เราจะยาวมาก T T)

จากนั้นเราเพิ่มเงื่อนไขใน WHERE clause เข้าไปให้ข้อมูลอยู่ในช่วงวันที่ 22-30 มิถุนายน 2024 อีกนิดก็เรียบร้อย

-- Employees with the Highest Sales (June 26-29, 2024)

SELECT 
  st.name                     AS Staff_Name,
  SUM(me.price * tr.quantity) AS Total_Sale
FROM staffs AS st,
     transactions AS tr,
     menus AS me
WHERE st.staff_id = tr.staff_id AND tr.menu_id = me.menu_id
AND (invoicedate BETWEEN '2024-06-22' AND '2024-06-30')
GROUP BY 1
ORDER BY 2 DESC;

จาก result จะเห็นว่า Ice เป็นคนที่ทำยอดขายในช่วงวันที่ 22-30 มิถุนายน 2024 ได้มากที่สุด รองลงมา คือ James และ Pon

Subqueries

ถ้าให้พูดง่ายๆการเขียน subqueries คือ การเขียน query ซ้อน query

ในการเขียน query บางครั้ง เราจำเป็นต้องรัน query มากกว่า 1 query เพื่อให้ได้ result ที่เราต้องการ แต่จริงๆเราสามารถใช้ subqueries เขียนจบในครั้งเดียวเลย

รูปภาพจากหนังสือ Practical SQL Data Analytics Series Final version 2.0 – DataRockie

หลักการทำงานของ subqueries คือ code จะรันจาก inner query ชั้นในสุดก่อนไล่ไปเรื่อยๆจนถึง query ชั้นนอกสุด (outer query)

โดยส่วนใหญ่เรามักจะ subqueries ได้ที่ WHERE, FROM, JOIN และ SELECT clause ซึ่งตำแหน่งที่มักจะเจอง่ายที่สุดคือ WHERE clause

แต่จากแผนภาพเราน่าจะเห็นข้อเสียของวิธีนี้แล้ว คือ ถ้ามี query มากเกินไป อาจจะทำให้ code เราอ่านยาก แก้ไขยากมาก

1. Top Customer 5 คนที่มาคาเฟ่บ่อยที่สุดตั้งแต่วันที่ 25 มิถุนายน 2024

สิ่งที่เราต้องทราบก่อนเลยคือ จำนวนที่ลูกค้าแต่ละคนเข้ามาใช้บริการ​
ซึ่งสามารถเขียน query ได้จาก table transactions ตามปกติเลย

SELECT 
  customer_id, 
  COUNT(*) 
FROM transactions AS tr
WHERE tr.invoicedate >= '2024-06-25'
GROUP BY 1
ORDER BY 2 DESC
LIMIT 5;

แต่สิ่งที่เราอยากรู้จริงๆคือใครคือ 5 คนนั้นบ้าง นั่นคือ ชื่อลูกค้าทั้ง 5 คน
ทำให้ตอนเรา SELECT ชื่อลูกค้ามา เราจะฟิลเตอร์เฉพาะลูกค้าที่มี id ตาม result ข้างบนนี้

-- Top 5 customers with the most visits since June 25, 2024

SELECT
  cu.name AS Customer_Name
FROM customers AS cu
WHERE customer_id IN (
   SELECT customer_id FROM (
       SELECT customer_id, COUNT(*) 
       FROM transactions AS tr
       WHERE tr.invoicedate >= '2024-06-25'
       GROUP BY 1
       ORDER BY 2 DESC
       LIMIT 5
       )
);

สังเกตว่า query นี้ จะเริ่มรันจาก inner query สีเหลืองก่อน แล้วไล่ไปที่ inner query สีม่วง จนถึง outer query ชั้นนอกสุด

จาก result จะเห็นว่า ลูกค้า 5 คนที่มาใช้บริการบ่อยที่สุด คือ Tan, New, Dew, Boss และ Ta

2. เมนู category ไหนขายดีที่สุด

ขั้นแรก เราจะต้องรู้ก่อนว่ายอดขายทั้งหมดของแต่ละ category ก่อน ดังนั้น เรามาลองเขียน query นี้กันก่อนเลย

SELECT 
  me.category AS Category,
  SUM(me.price * tr.quantity) AS Total_Sales
FROM 
  menus AS me, 
  transactions AS tr
WHERE me.menu_id = tr.menu_id
GROUP BY 1
ORDER BY 2 DESC;

แต่เราอยากรู้แค่ว่าเมนู category ไหนขายดีที่สุด เราก็แค่ SELECT เฉพาะ Category มาแล้ว LIMIT แค่อันดับ 1 เท่านั้น

-- Most popular category menu

SELECT 
  Category
FROM (
  SELECT 
    me.category AS Category,
    SUM(me.price * tr.quantity) AS Total_Sales
  FROM 
    menus AS me, 
    transactions AS tr
  WHERE me.menu_id = tr.menu_id
  GROUP BY 1
  ORDER BY 2 DESC
)
LIMIT 1;

จาก result เราจะได้ว่า เมนูที่ขายดีที่สุด คือ เมนูประเภท classic coffee นั่นเอง

ก่อนจะไปที่หัวข้อสุดท้ายกัน อยากให้ทุกคนลองช่วยกันสังเกตหน่อยว่า จากทั้งสองตัวอย่างนี้เราเขียน subqueries ไว้ที่ไหนกันบ้าง?

Common Table Expression (CTEs)

Common Table Expression (CTEs) คือ การสร้าง Temporary Result Set เหมือนการประกาศตัวแปรเพื่อเรียกใช้งานต่อภายหลังเลย

ซึ่งข้อดีของการใช้ CTE เลยคือการ break subqueries ของเราที่เป็นปัญหาของเราก่อนหน้านี้ได้ ทำให้ code ของเราอ่านง่ายขึ้น แต่ยังได้ result เหมือนเดิมเป๊ะ! แถมยังสามารถนำไปใช้ใน query อื่นได้ด้วย

1. Top Spender 5 คนแรกที่มาคาเฟ่บ่อยที่สุดตั้งแต่วันที่ 25 มิถุนายน 2024

จากตัวอย่างที่ 1 ในการใช้ subqueries ที่ผ่านมา เราสามารถนำ inner query ชั้นในสุดมาเขียนเป็น CTE โดยใช้ WITH clause ได้

-- Top 5 customers with the most visits since June 25, 2024

WITH Top5_CustomersID_MostVisit AS (
  SELECT customer_id, COUNT(*)
  FROM transactions AS tr
  WHERE tr.invoicedate >= '2024-06-25'
  GROUP BY 1
  ORDER BY 2 DESC
  LIMIT 5
)

SELECT
  cu.name AS Customer_Name
FROM customers AS cu
WHERE customer_id IN (
   SELECT customer_id FROM Top5_CustomerID_MostVisit
);

2. ระหว่างเครื่องดื่มหรือขนม category ไหนขายดีที่สุด

จากตัวอย่างที่ 2 ก่อนหน้านี้ อันนี้ง่ายเลย เราแค่นำ subqueries ใน FROM clause มาสร้างเป็น CTE ใน WITH clause ก่อน โดยเราตั้งชื่อเป็น Total_Sales_by_Category

-- Most popular category menu

WITH Total_Sales_by_Category AS (
  SELECT 
    me.category AS Category,
    SUM(me.price * tr.quantity) AS Total_Sales
  FROM 
    menus AS me, 
    transactions AS tr
  WHERE me.menu_id = tr.menu_id
  GROUP BY 1
  ORDER BY 2 DESC
)

SELECT 
  Category
FROM Total_Sales_by_Category
LIMIT 1;

สรุปสิ่งที่เราได้จากบทความนี้ว่า ก่อนเราจะหา insight ในธุรกิจได้ เริ่มต้นจาก

  • การทำความเข้าใจธุรกิจ
  • ออกแบบ database ให้ดี
  • สร้าง database ที่มั่นคง
  • หา insight จาก database เพื่อสร้าง value ให้กับธุรกิจด้วย 3 เทคนิค

ทุกคนลองนำแนวทางนี้ที่เราฝากไว้ไปสร้างบ้านของตัวเองให้มั่นคง แข็งแรงนะ

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


Comments

Leave a comment


Comments

Leave a comment