วัตถุประสงค์การเรียนรู้
เมื่อจบบทนี้ ผู้เรียนจะสามารถ
- ใช้ Text Functions ที่สำคัญ ได้แก่
UPPER,LOWER,CONCAT,REPLACE,LENGTH,SUBSTRING,LEFT,RIGHTเพื่อจัดการกับข้อความให้เหมาะกับการใช้งานเชิงธุรกิจ - แปลงชนิดข้อมูลด้วย
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() เชื่อมทั้งข้อความและตัวเลข
แบบที่ 2: ใช้ตัวดำเนินการ || เพื่อเชื่อมสตริงแทนการใช้ CONCAT()
| 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 ใช้แปลงค่าหรือนิพจน์จากชนิดข้อมูลหนึ่งไปเป็นอีกชนิดข้อมูลหนึ่ง เช่น จากข้อความเป็นตัวเลข จากข้อความเป็นวันที่ หรือจากเลขทศนิยมเป็นจำนวนเต็ม
รูปแบบคำสั่ง
expressionคือค่าหรือคอลัมน์ที่ต้องการแปลง
data_typeคือชนิดข้อมูลเป้าหมาย เช่นINT,DECIMAL,DATE,DATETIME,CHAR
- ถ้าการแปลงทำไม่ได้ (เช่น
'ABC'แปลงเป็นINT) จะเกิด error
TRY_CAST ทำงานคล้าย CAST แต่เพิ่มความปลอดภัย ถ้าแปลงสำเร็จจะคืนค่าที่ถูกแปลงแล้ว แต่ถ้าแปลงไม่ได้จะคืนค่า NULL แทนการโยน error ทำให้คำสั่งทั้งชุดยังรันต่อได้
รูปแบบคำสั่ง
- พารามิเตอร์เหมือน
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 เพื่อวิเคราะห์แนวโน้มรายเดือน รายวัน และรายชั่วโมง
คำถามท้ายบท
- ใช้
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; -- เรียงจากสาขาที่มีรายได้รวมสูงสุด- วิเคราะห์ความยาวชื่อเมนูด้วย
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; -- เรียงจากชื่อที่มีความยาวมากสุดไปน้อยสุด- ค้นหาและแทนที่ข้อความด้วย
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; -- เรียงตามหมวดหมู่ จากนั้นเรียงตามราคาจากน้อยไปมาก