วัตถุประสงค์การเรียนรู้

เมื่อจบบทนี้ ผู้เรียนจะสามารถ

  1. ใช้ Text Functions ที่สำคัญ ได้แก่ UPPER, LOWER, CONCAT, REPLACE, LENGTH, SUBSTRING, LEFT, RIGHT เพื่อจัดการกับข้อความให้เหมาะกับการใช้งานเชิงธุรกิจ
  2. แปลงชนิดข้อมูลด้วย CAST และ TRY_CAST เพื่อเตรียมข้อมูลให้พร้อมใช้ร่วมกับฟังก์ชันข้อความ

บทนำ

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

บทนี้จึงแนะนำทั้งฟังก์ชันจัดการข้อความ (Text Functions) และฟังก์ชันสำหรับแปลงชนิดข้อมูล ได้แก่ CAST และ TRY_CAST ซึ่งมีบทบาทสำคัญในการทำความสะอาด ตัดต่อ และจัดรูปแบบข้อมูลให้พร้อมใช้งาน โดยไม่จำเป็นต้องแก้ไขข้อมูลต้นฉบับที่จัดเก็บอยู่ในตาราง

แนวคิดสำคัญของบทนี้คือ การใช้ Text Functions เพื่อปรับรูปแบบข้อความให้เหมาะกับการแสดงผลสำหรับผู้ใช้ ขณะเดียวกันก็ใช้ CAST และ TRY_CAST เพื่อเตรียมชนิดข้อมูลให้ถูกต้องก่อนนำไปคำนวณ เปรียบเทียบ หรือเชื่อมต่อกับข้อความอื่นในงานวิเคราะห์ข้อมูล

Text/String Functions: จัดการข้อความให้พร้อมใช้งานรายงาน

ส่วนนี้รวบรวมฟังก์ชันข้อความพื้นฐานที่ใช้บ่อยในการจัดการสตริง ทั้งการเปลี่ยนรูปแบบตัวอักษร นับความยาว แทนที่คำ ตัดบางส่วนออก และประกอบข้อความจากหลายคอลัมน์

ฟังก์ชัน ตัวอย่าง ผลลัพธ์
UPPER(text) UPPER('PiCha') ‘PICHA’
LOWER(text) LOWER('PiCha') ‘picha’
LENGTH(text) LENGTH('PiCha') 5
CONCAT(a, b) CONCAT('Pi', 'Cha') ‘PiCha’
REPLACE(text, old, new) REPLACE('PiCha Store', 'PiCha ', '') ‘Store’
LEFT(text, n) LEFT('PiCha', 2) ‘Pi’
RIGHT(text, n) RIGHT('PiCha', 3) ‘Cha’
SUBSTRING(text, start, len) SUBSTRING('PiCha', 1, 2) ‘Pi’

ทำความสะอาดและจัดรูปแบบชื่อสาขา

ตัวอย่างแรกใช้ข้อมูลจากตาราง stores เพื่อแสดงการใช้ฟังก์ชันข้อความพื้นฐานในการจัดการชื่อสาขาให้พร้อมใช้ในรายงาน โดยยังเก็บข้อมูลต้นฉบับไว้เหมือนเดิม

SELECT
 store_name,                            -- ชื่อสาขาตามที่เก็บในตาราง (ต้นฉบับ)
 UPPER(store_name) AS store_name_upper, -- แปลงชื่อสาขาเป็นตัวพิมพ์ใหญ่ทั้งหมด เช่น 'PiCha Cafe' -> 'PICHA CAFE' 
 LOWER(store_name) AS store_name_lower, -- แปลงชื่อสาขาเป็นตัวพิมพ์เล็กทั้งหมด เช่น 'PiCha Cafe' -> 'picha cafe' 
 LENGTH(store_name) AS name_length,     -- นับจำนวนตัวอักษรในชื่อสาขา (รวมช่องว่างและสัญลักษณ์) 
 SUBSTRING(store_name, 7) AS name_from_7th_char,     -- ตัดเอาข้อความตั้งแต่ตัวที่ 7 เป็นต้นไปในชื่อสาขา เช่น 'PiCha Cafe' -> 'Cafe' ถ้า index 7 คือ C 
 REPLACE(store_name, 'PiCha ', '') AS brand_removed, -- แทนที่คำว่า 'PiCha ' ด้วยข้อความว่าง เพื่อลบแบรนด์ออก เช่น 'PiCha Cafe A' -> 'Cafe A' 
 CONCAT(store_name, ' (', district, ')') AS formatted_name -- เอาชื่อสาขามาต่อกับชื่อเขตในวงเล็บ เช่น 'PiCha Cafe' + ' (Bang Rak)' 
FROM stores                                        
ORDER BY store_id;                                  
store_name store_name_upper store_name_lower name_length name_from_7th_char brand_removed formatted_name
PiCha centralwOrld PICHA CENTRALWORLD picha centralworld 18 centralwOrld centralwOrld PiCha centralwOrld (Pathum Wan)
PiCha Siam Square PICHA SIAM SQUARE picha siam square 17 Siam Square Siam Square PiCha Siam Square (Pathum Wan)
PiCha Park Silom PICHA PARK SILOM picha park silom 16 Park Silom Park Silom PiCha Park Silom (Bang Rak)
PiCha Exchange Tower PICHA EXCHANGE TOWER picha exchange tower 20 Exchange Tower Exchange Tower PiCha Exchange Tower (Khlong Toei)
PiCha Vanit Village PICHA VANIT VILLAGE picha vanit village 19 Vanit Village Vanit Village PiCha Vanit Village (Ratchathewi)
PiCha ICONSIAM PICHA ICONSIAM picha iconsiam 14 ICONSIAM ICONSIAM PiCha ICONSIAM (Khlong San)

จากผลลัพธ์จะเห็นว่าชื่อสาขายาวสุดคือ Exchange Tower (20 อักขระ) และสั้นสุดคือ ICONSIAM (14 อักขระ) ทำให้เปรียบเทียบความยาวชื่อในแต่ละทำเลได้ชัดเจนขึ้น REPLACE ตัดชื่อ brand ‘PiCha’ ออกได้อย่างสะอาด ในขณะที่ SUBSTRING ตัดจากตัวอักษรที่ 7 เป็นต้นไปให้ผลลัพธ์ส่วนชื่อสาขาเหมือนกัน

ฟังก์ชัน CONCAT และ REPLACE จึงทำหน้าที่สำคัญในการสร้างชื่อสาขาแบบที่ถูกจัดรูปแบบให้อ่านง่ายสำหรับรายงาน โดยไม่ต้องแก้ไขข้อมูลต้นฉบับในตาราง

ตัดแยกบางส่วนของข้อความจากชื่อเมนู

ตัวอย่างก่อนหน้าทำงานกับสตริงทั้งตัว แต่ในหลายกรณีเราต้องการ “ดึงบางส่วนของข้อความออกมา” เช่น ตัดเอาเฉพาะชื่อสาขา หรือดึงรหัสขนาดออกจากชื่อเมนู SQL มีฟังก์ชัน LEFT, RIGHT และ SUBSTRING สำหรับงานลักษณะนี้

ตัวอย่างต่อไปใช้ข้อมูลจากตาราง menus เพื่อสาธิตการย่อชื่อเมนูและการแยกขนาดสินค้าออกจากชื่อเดียวกัน

SELECT
 sku_name,
 LEFT(sku_name, 7) AS short_name, -- `LEFT(sku_name, 7)` = นับจากซ้าย 7 ตัวอักษร → ได้ชื่อย่อที่พอเดาได้ว่าเมนูอะไร
 RIGHT(sku_name, 1) AS size, -- นับจากขวา 1 ตัวอักษร → ได้ size ทันที ไม่ต้องรู้ว่าชื่อยาวแค่ไหน
 SUBSTRING(sku_name, 1, LENGTH(sku_name) - 2) AS name_no_size -- เริ่มจากตัวแรก ตัดออก 2 ตัวสุดท้าย (space + R/L) → เหลือแค่ชื่อเมนู
FROM menus
LIMIT 5;
sku_name short_name size name_no_size
Glutinous Green Milk Tea R Glutino R Glutinous Green Milk Tea
Glutinous Green Milk Tea L Glutino L Glutinous Green Milk Tea
Tie Guan Yin Milk Tea R Tie Gua R Tie Guan Yin Milk Tea
Tie Guan Yin Milk Tea L Tie Gua L Tie Guan Yin Milk Tea
Da Hong Pao Milk Tea R Da Hong R Da Hong Pao Milk Tea

จากตารางข้างต้น สังเกตว่า RIGHT(sku_name, 1) ดึงตัว R หรือ L ออกมาได้ทันทีโดยไม่ต้องรู้ความยาวชื่อ นี่คือจุดแข็งของ RIGHT ที่นับจากท้ายสตริงเข้ามา ส่วน LEFT และ SUBSTRING ช่วยให้ตัดชื่อเมนูส่วนที่ต้องการออกมาได้อย่างยืดหยุ่นสำหรับหน้าจอที่มีพื้นที่จำกัด เช่น POS หรือ dashboard

สรุปฟังก์ชันตัดบางส่วนของข้อความ

ฟังก์ชัน นับจาก ใช้เมื่อ
LEFT(text, n) ซ้าย → ขวา รู้ว่าต้องการกี่ตัวอักษรจากทางซ้ายของข้อความ
RIGHT(text, n) ขวา → ซ้าย ข้อมูลที่ต้องการอยู่ตัวท้ายข้อความ เช่น size, code
SUBSTRING(text, start, len) ตำแหน่งที่กำหนด ต้องการดึงส่วนของข้อความโดยระบุตำแหน่งเริ่มต้นและจำนวนตัวอักษรที่ต้องการ

เมื่อสามารถตัดแยกข้อความได้แล้ว คำถามถัดมาคือ “ถ้าต้องการเอาข้อมูลจากหลายคอลัมน์มาประกอบกันเป็นข้อความเดียวล่ะ?”

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

ประกอบสตริงและตัวเลขเป็น label เดียว

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

ตัวอย่างนี้ต้องการสร้างคอลัมน์ menu ที่เก็บชื่อเมนูและราคาขายพร้อมกัน

แบบที่ 1: ใช้ฟังก์ชัน CONCAT() เชื่อมทั้งข้อความและตัวเลข

SELECT CONCAT(sku_name, ' (', list_price_thb, ' THB)') AS menu
FROM menus
LIMIT 5;

แบบที่ 2: ใช้ตัวดำเนินการ || เพื่อเชื่อมสตริงแทนการใช้ CONCAT()

SELECT sku_name || ' (' || list_price_thb || ' THB)' AS menu
FROM menus
LIMIT 5;
menu
Glutinous Green Milk Tea R (85 THB)
Glutinous Green Milk Tea L (100 THB)
Tie Guan Yin Milk Tea R (110 THB)
Tie Guan Yin Milk Tea L (130 THB)
Da Hong Pao Milk Tea R (110 THB)

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

สร้างรายงานสาขาแบบจัดรูปแบบพร้อมระดับความพึงพอใจ

ตัวอย่างถัดไปยกระดับจากการต่อชื่อเมนูกับราคา ไปเป็นการสร้าง “การ์ดสรุปสาขา” โดยใช้ CONCAT ร่วมกับ CASE, ROUND และ aggregate functions เป้าหมายคือสร้าง 3 label ต่อสาขา: ป้ายชื่อสาขา ป้ายรายได้รวม และป้ายระดับความพึงพอใจ

-- สรุปรายได้และระดับความพึงพอใจแบบ label แยกตามสาขา
SELECT
 CONCAT(UPPER(SUBSTRING(s.store_name, 1, 3)), ' - ', s.store_name) AS store_label, -- ป้ายชื่อสาขา: อักษรย่อตัวพิมพ์ใหญ่ 3 ตัว + ชื่อเต็ม
 CONCAT(
   CAST(ROUND(SUM(t.net_sales_thb) / 1000, 0) AS VARCHAR),
   'K THB'
 ) AS revenue_label, -- ป้ายรายได้รวม (แสดงเป็นหน่วยพัน เช่น 1,234K THB)
 CONCAT(
   CASE
     WHEN AVG(t.satisfaction_score) >= 4.2 THEN 'Excellent' -- คะแนนความพึงพอใจดีเยี่ยม
     WHEN AVG(t.satisfaction_score) >= 4.0 THEN 'Good'      -- คะแนนความพึงพอใจดี
     ELSE 'Needs Work'                                       -- คะแนนความพึงพอใจต้องปรับปรุง
   END,
   ' (', ROUND(AVG(t.satisfaction_score), 2), ')'
 ) AS satisfaction_label -- ป้ายระดับความพึงพอใจพร้อมคะแนน เช่น Good (4.15)
FROM transactions t
JOIN stores s ON t.store_id = s.store_id -- เชื่อมตารางสาขาเพื่อดึงชื่อสาขา
GROUP BY s.store_name -- จัดกลุ่มตามชื่อสาขา
ORDER BY SUM(t.net_sales_thb) DESC; -- เรียงจากสาขาที่มีรายได้รวมสูงสุด
store_label revenue_label satisfaction_label
PIC - PiCha centralwOrld 2451K THB Good (4.19)
PIC - PiCha Siam Square 2312K THB Needs Work (3.96)
PIC - PiCha ICONSIAM 1764K THB Excellent (4.53)
PIC - PiCha Vanit Village 1466K THB Good (4.07)
PIC - PiCha Park Silom 1451K THB Needs Work (3.66)
PIC - PiCha Exchange Tower 1344K THB Needs Work (3.63)

จะเห็นว่าตัวอย่างนี้นำทุกอย่างที่เรียนมาก่อนหน้าไปใช้ร่วมกัน ทั้งการตัดบางส่วนของข้อความ (SUBSTRING), การปรับรูปแบบ (UPPER), การคำนวณตัวเลข (SUM, AVG, ROUND) และการต่อข้อความ (CONCAT) เพื่อสร้าง label ที่พร้อมใช้ในรายงาน

จุดสำคัญคือ แม้ label จะถูกสร้างขึ้นใหม่ทั้งหมด แต่ข้อมูลต้นฉบับในตาราง transactions และ stores ไม่ถูกแก้ไขเลย

ส่วนถัดไปจึงโฟกัสที่ฟังก์ชันสำหรับแปลงชนิดข้อมูล โดยเฉพาะ CAST และ TRY_CAST ซึ่งมักใช้ควบคู่กับฟังก์ชันข้อความในงานวิเคราะห์จริง

CAST และ TRY_CAST

CAST และ TRY_CAST ใช้สำหรับ “แปลงชนิดข้อมูล” แต่ต่างกันตรงที่ CAST ถ้าแปลงไม่ได้จะเป็น error ในขณะที่ TRY_CAST ถ้าแปลงไม่ได้จะคืนค่า NULL แทน

ข้อมูลจริงมักมีชนิดข้อมูลไม่ตรงกับรูปแบบที่ต้องการใช้งาน เช่น ตัวเลขที่ต้องแสดงเป็นข้อความสำหรับ label หรือวันที่ที่เก็บเป็น string ต้องแปลงเป็น DATE ก่อนคำนวณ ฟังก์ชัน CAST และ TRY_CAST ช่วยจัดการปัญหานี้

CAST ใช้แปลงค่าหรือนิพจน์จากชนิดข้อมูลหนึ่งไปเป็นอีกชนิดข้อมูลหนึ่ง เช่น จากข้อความเป็นตัวเลข จากข้อความเป็นวันที่ หรือจากเลขทศนิยมเป็นจำนวนเต็ม

รูปแบบคำสั่ง

CAST(expression AS data_type[(length)])
  • expression คือค่าหรือคอลัมน์ที่ต้องการแปลง
  • data_type คือชนิดข้อมูลเป้าหมาย เช่น INT, DECIMAL, DATE, DATETIME, CHAR
  • ถ้าการแปลงทำไม่ได้ (เช่น 'ABC' แปลงเป็น INT) จะเกิด error

TRY_CAST ทำงานคล้าย CAST แต่เพิ่มความปลอดภัย ถ้าแปลงสำเร็จจะคืนค่าที่ถูกแปลงแล้ว แต่ถ้าแปลงไม่ได้จะคืนค่า NULL แทนการโยน error ทำให้คำสั่งทั้งชุดยังรันต่อได้

รูปแบบคำสั่ง

TRY_CAST(expression AS data_type[(length)])
  • พารามิเตอร์เหมือน CAST
  • ถ้าแปลงไม่สำเร็จจะได้ NULL แทน

การแปลงชนิดข้อมูลในตารางสาขา

-- ทดสอบการแปลงประเภทข้อมูล (Type Casting) ในตารางสาขา
SELECT
 store_id, -- รหัสสาขา (INTEGER)
 CAST(store_id AS VARCHAR) AS store_id_text, -- แปลงรหัสสาขาเป็น TEXT
 CAST(monthly_rent_thb AS DOUBLE) / 1000 AS rent_in_k, -- แปลงค่าเช่าเป็น DOUBLE (ทศนิยม) แล้วหารพัน (หน่วย K บาท)
 TRY_CAST('2026-04-01' AS DATE) AS parsed_date, -- แปลง string เป็น DATE (TRY_CAST ไม่ error ถ้าแปลงไม่ได้)
 CAST(opening_date AS VARCHAR) AS opening_date_text, -- แปลงวันที่เปิดสาขาเป็น TEXT
 parsed_date - opening_date AS operation_days -- จำนวนวันที่สาขาดำเนินกิจการ
FROM stores -- ตารางข้อมูลสาขา
LIMIT 3; -- แสดงเพียง 3 แถวแรกสำหรับทดสอบ
store_id store_id_text rent_in_k parsed_date opening_date_text operation_days
1 1 180.0 2026-04-01 2025-03-01 396
2 2 250.0 2026-04-01 2025-04-15 351
3 3 95.0 2026-04-01 2025-05-10 326

ตัวอย่างนี้แสดงรูปแบบการใช้ CAST และ TRY_CAST แบบผสมผสาน เช่น

  • แปลง store_id จากตัวเลขเป็นข้อความเพื่อเอาไปต่อกับสตริงอื่นใน label
  • แปลง monthly_rent_thb เป็น DOUBLE เพื่อหารพันให้เป็นหน่วย K บาท
  • แปลงสตริง ‘2026-04-01’ เป็น DATE เพื่อใช้คำนวณระยะเวลาการดำเนินการของสาขา

ใน data pipeline ที่ประมวลผลข้อมูลจำนวนมาก TRY_CAST มักเป็นตัวเลือกแรก เพราะป้องกันไม่ให้ query ล้มเหลวกลางคัน แถวที่แปลงไม่ได้จะกลายเป็น NULL ซึ่งสามารถตรวจจับทีหลังด้วยเงื่อนไข WHERE ... IS NULL หรือจัดการด้วย COALESCE ได้เช่นกัน

สรุป

ตลอดทั้งบทนี้ เราใช้ตัวอย่างจากข้อมูลสาขาและเมนูเครื่องดื่มเพื่อฝึกฝน 2 ทักษะสำคัญในการเตรียมข้อมูล ได้แก่ การจัดการข้อความด้วย Text Functions และการแปลงชนิดข้อมูลด้วย CAST / TRY_CAST เพื่อให้ข้อมูลอยู่ในรูปแบบที่พร้อมสำหรับการวิเคราะห์ การสรุปผล และการนำไปใช้ในรายงาน

ฟังก์ชันกลุ่มข้อความช่วยให้เราปรับแต่งข้อมูลให้สื่อความหมายชัดเจนและมีรูปแบบสม่ำเสมอมากขึ้น เช่น การรวมข้อความ การเปลี่ยนตัวพิมพ์ หรือการตัดบางส่วนของสตริง ขณะที่ CAST และ TRY_CAST ช่วยแปลงข้อมูลให้เหมาะกับการคำนวณและการประมวลผลต่อไป เช่น การแปลงข้อความให้เป็นตัวเลขหรือวันที่ ตารางต่อไปนี้สรุป syntax หน้าที่หลัก และตัวอย่างการประยุกต์ใช้เชิงธุรกิจของแต่ละฟังก์ชัน

แนวคิด Syntax หน้าที่ การใช้ธุรกิจ
CONCAT CONCAT(a, ' ', b) เชื่อมข้อความหลายส่วนเข้าด้วยกัน สร้างป้ายชื่อหรือ label สำหรับเมนูและสาขาให้อ่านง่าย
UPPER/LOWER UPPER(col), LOWER(col) แปลงข้อความเป็นตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็ก ทำให้รูปแบบข้อความสม่ำเสมอก่อนนำไปวิเคราะห์
REPLACE REPLACE(col, 'old', 'new') แทนที่ข้อความบางส่วน แก้คำสะกดที่ไม่ตรงกัน หรือปรับข้อความให้เหมาะกับบริบทภาษาไทย
SUBSTRING SUBSTRING(col, start, len) ดึงข้อความบางช่วงออกจากสตริง แยกคำสำคัญหรือรหัสจากข้อความที่ยาว
LEFT / RIGHT LEFT(col, n), RIGHT(col, n) ดึงข้อความจากด้านซ้ายหรือด้านขวาของสตริง ย่อชื่อให้พอดีกับหน้าจอ หรือดึงรหัสและขนาดสินค้าจากท้ายชื่อ
LENGTH LENGTH(col) นับจำนวนอักขระในข้อความ ตรวจสอบว่าชื่อเมนูหรือชื่อสาขายาวเกินไปสำหรับการแสดงผลหรือไม่
CAST CAST(col AS type) แปลงชนิดข้อมูล เตรียมข้อมูลตัวเลขหรือวันที่ให้อยู่ในรูปแบบที่พร้อมคำนวณ
TRY_CAST TRY_CAST(col AS type) แปลงชนิดข้อมูลแบบปลอดภัย ลดความเสี่ยงจาก error เมื่อข้อมูลบางแถวมีรูปแบบไม่ถูกต้องใน pipeline

บทถัดไปจะขยายทักษะการแปลงและจัดรูปแบบข้อมูลไปสู่มิติเวลา โดยใช้ Date/Time Functions เพื่อวิเคราะห์แนวโน้มรายเดือน รายวัน และรายชั่วโมง

คำถามท้ายบท

  1. ใช้ CONCAT และ UPPER สร้าง formatted label สำหรับแต่ละสาขาแบบ “BRANCH_NAME (DISTRICT) - TOTAL_REVENUE THB”

ผลลัพธ์ที่คาดหวัง

branch_label
PICHA CENTRALWORLD (PATHUM WAN) - 2451113.42 THB
PICHA SIAM SQUARE (PATHUM WAN) - 2311859.88 THB
PICHA ICONSIAM (KHLONG SAN) - 1763926.15 THB
PICHA VANIT VILLAGE (RATCHATHEWI) - 1465763.85 THB
PICHA PARK SILOM (BANG RAK) - 1450876.88 THB
PICHA EXCHANGE TOWER (KHLONG TOEI) - 1343861.3 THB
คลิกเพื่อดูเฉลย
-- สร้าง Label สรุปรายได้รวมของแต่ละสาขาในรูปแบบ "ชื่อสาขา (เขต) - รายได้ THB"
SELECT
 CONCAT(
     UPPER(s.store_name),  -- ชื่อสาขาตัวพิมพ์ใหญ่
     ' (',
     UPPER(s.district),    -- ชื่อเขตตัวพิมพ์ใหญ่
     ') - ',
     ROUND(SUM(t.net_sales_thb), 2), -- รายได้รวม (บาท ทศนิยม 2 ตำแหน่ง)
     ' THB'
 ) AS branch_label -- ตัวอย่าง: PICHA SIAM (PATHUM WAN) - 1234567.89 THB
FROM transactions t
JOIN stores s ON t.store_id = s.store_id -- เชื่อมตารางสาขาเพื่อดึงชื่อและเขต
GROUP BY s.store_id, s.store_name, s.district -- จัดกลุ่มตามสาขา
ORDER BY SUM(t.net_sales_thb) DESC; -- เรียงจากสาขาที่มีรายได้รวมสูงสุด
  1. วิเคราะห์ความยาวชื่อเมนูด้วย LENGTH และ LOWER

ทีม Product ต้องการตรวจสอบชื่อเมนูทั้งหมด โดยแสดง

  • ชื่อเมนูในรูปแบบ lowercase
  • ความยาวของชื่อเมนู (จำนวนตัวอักษร)
  • family ของเมนู

เรียงตามความยาวชื่อจากมากไปน้อย เพื่อดูว่าชื่อเมนูไหนยาวเกินไปสำหรับการแสดงผลบนหน้าจอ

ผลลัพธ์ที่คาดหวัง

sku_name sku_name_lower name_length family
Lemon Glutinous Green Tea L lemon glutinous green tea l 27 fruit_tea
Glutinous Green Milk Tea R glutinous green milk tea r 26 milk_tea
Glutinous Green Milk Tea L glutinous green milk tea l 26 milk_tea
Fresh Orange Jasmine Tea L fresh orange jasmine tea l 26 fruit_tea
Glutinous Green Pure Tea R glutinous green pure tea r 26 pure_tea
Jasmine Grapefruit Tea L jasmine grapefruit tea l 24 fruit_tea
Tie Guan Yin Milk Tea R tie guan yin milk tea r 23 milk_tea
Tie Guan Yin Milk Tea L tie guan yin milk tea l 23 milk_tea
Tie Guan Yin Pure Tea R tie guan yin pure tea r 23 pure_tea
Mango Sticky Rice Tea L mango sticky rice tea l 23 fruit_tea
Da Hong Pao Milk Tea R da hong pao milk tea r 22 milk_tea
Da Hong Pao Milk Tea L da hong pao milk tea l 22 milk_tea
White Peach Milk Tea R white peach milk tea r 22 milk_tea
White Peach Milk Tea L white peach milk tea l 22 milk_tea
Osmanthus Milk Tea R osmanthus milk tea r 20 milk_tea
Osmanthus Milk Tea L osmanthus milk tea l 20 milk_tea
Peach Jasmine Tea L peach jasmine tea l 19 fruit_tea
Jasmine Milk Tea R jasmine milk tea r 18 milk_tea
Jasmine Milk Tea L jasmine milk tea l 18 milk_tea
Thai Tea Frappe L thai tea frappe l 17 blended
Pu’er Milk Tea R pu’er milk tea r 16 milk_tea
Pu’er Milk Tea L pu’er milk tea l 16 milk_tea

การใช้ LENGTH() ทำให้ทีม UX เห็นว่าชื่อเมนูใดยาวเกินจำนวนตัวอักษรที่ยอมรับได้ เช่น เกิน 30 ตัวอักษร ซึ่งอาจต้องพิจารณาตัดหรือย่อเมื่อแสดงบนหน้าจอ ส่วน LOWER() ช่วยเปลี่ยนทุกชื่อให้เป็นตัวพิมพ์เล็กทั้งหมด ทำให้เปรียบเทียบชื่อแบบ case-insensitive ได้ง่าย และลดปัญหาข้อมูลซ้ำที่เกิดจากรูปแบบตัวอักษรต่างกัน

คลิกเพื่อดูเฉลย
-- แสดงชื่อเมนูพร้อมตัวพิมพ์เล็กและความยาวชื่อ เรียงจากชื่อยาวที่สุด
SELECT
 sku_name, -- ชื่อเมนูต้นฉบับ
 LOWER(sku_name) AS sku_name_lower, -- ชื่อเมนูแปลงเป็นตัวพิมพ์เล็กทั้งหมด
 LENGTH(sku_name) AS name_length, -- จำนวนตัวอักษรในชื่อเมนู
 family -- หมวดหมู่เมนู
FROM menus -- ตารางข้อมูลเมนู
ORDER BY name_length DESC; -- เรียงจากชื่อที่มีความยาวมากสุดไปน้อยสุด
  1. ค้นหาและแทนที่ข้อความด้วย REPLACE และ LIKE

ทีม Operations ต้องการดูรายการเมนูในกลุ่ม milk_tea ทั้งหมด และสร้าง display name ใหม่โดย - แทนที่คำว่า "Milk Tea" ด้วย "ชานม" ใน display name - กรองเฉพาะเมนูที่มีคำว่า "Tea" อยู่ในชื่อ

REPLACE() มีประโยชน์มากในงาน localize ข้อมูลสำหรับลูกค้าที่ใช้ภาษาไทย โดยไม่ต้องแก้ไขข้อมูลต้นฉบับในฐานข้อมูล ส่วน LIKE '%Tea%' ใช้ wildcard % เพื่อค้นหาชื่อเมนูที่มีคำว่า “Tea” อยู่ในตำแหน่งใดก็ได้ ทำให้กรองข้อมูลได้ยืดหยุ่นโดยไม่ต้องระบุตำแหน่งตายตัว

ผลลัพธ์ที่คาดหวัง

sku_name display_name_th family list_price_thb
Thai Tea Frappe L Thai Tea Frappe L blended 125
Peach Jasmine Tea L Peach Jasmine Tea L fruit_tea 95
Jasmine Grapefruit Tea L Jasmine Grapefruit Tea L fruit_tea 105
Lemon Glutinous Green Tea L Lemon Glutinous Green Tea L fruit_tea 105
Mango Sticky Rice Tea L Mango Sticky Rice Tea L fruit_tea 135
Fresh Orange Jasmine Tea L Fresh Orange Jasmine Tea L fruit_tea 150
Glutinous Green Milk Tea R Glutinous Green ชานม R milk_tea 85
Pu’er Milk Tea R Pu’er ชานม R milk_tea 95
Osmanthus Milk Tea R Osmanthus ชานม R milk_tea 95
Jasmine Milk Tea R Jasmine ชานม R milk_tea 95
White Peach Milk Tea R White Peach ชานม R milk_tea 95
Glutinous Green Milk Tea L Glutinous Green ชานม L milk_tea 100
Tie Guan Yin Milk Tea R Tie Guan Yin ชานม R milk_tea 110
Da Hong Pao Milk Tea R Da Hong Pao ชานม R milk_tea 110
Pu’er Milk Tea L Pu’er ชานม L milk_tea 115
Osmanthus Milk Tea L Osmanthus ชานม L milk_tea 115
Jasmine Milk Tea L Jasmine ชานม L milk_tea 115
White Peach Milk Tea L White Peach ชานม L milk_tea 115
Tie Guan Yin Milk Tea L Tie Guan Yin ชานม L milk_tea 130
Da Hong Pao Milk Tea L Da Hong Pao ชานม L milk_tea 130
Glutinous Green Pure Tea R Glutinous Green Pure Tea R pure_tea 85
Tie Guan Yin Pure Tea R Tie Guan Yin Pure Tea R pure_tea 110
คลิกเพื่อดูเฉลย
-- ดึงเมนูที่มีคำว่า Tea ในชื่อ พร้อมแปลง "Milk Tea" เป็นภาษาไทย
SELECT
 sku_name, -- ชื่อเมนูภาษาอังกฤษ
 REPLACE(sku_name, 'Milk Tea', 'ชานม') AS display_name_th, -- แทนที่คำว่า Milk Tea ด้วย ชานม
 family, -- หมวดหมู่เมนู
 list_price_thb -- ราคาขาย (บาท)
FROM menus -- ตารางข้อมูลเมนู
WHERE sku_name LIKE '%Tea%' -- กรองเฉพาะเมนูที่มีคำว่า Tea ในชื่อ
ORDER BY family, list_price_thb; -- เรียงตามหมวดหมู่ จากนั้นเรียงตามราคาจากน้อยไปมาก