Professional Documents
Culture Documents
Practical SQL First Release 1.2
Practical SQL First Release 1.2
ั 1.2>
เขียนและเรียบเรียงโดย DataRockie
27 ธ.ค. 2562
📅 Update History
Practical SQL version 1.0 จํานวน 8 บท (24 ธ.ค. 2562)
Practical SQL version 1.1 จํานวน 14 บท (25 ธ.ค. 2562)
- เพิมเติมเนือหาในบท WHERE
- เพิมเติมเรือง Regular Expressions
- อัพเดท SQL Functions (Aggregate/ Value functions)
- อัพเดท GROUP BY
- อัพเดท HAVING
- อัพเดท ORDER BY
- อัพเดท JOIN
- อัพเดทการอัพโหลดไฟล์ CSV เข้าสู่ database
Practical SQL version 1.2 จํานวน 20 บท (27 ธ.ค. 2562)
- แก้ไขคําผิด และปรับ caption ของ diagram บางจุด
- เพิมเติมเรือง CROSS JOIN และ SELF JOIN
- อัพเดท CREATE TABLE
- อัพเดท CASE
- อัพเดท CAST
- อัพเดท Subqueries ครบทุกแบบ
- อัพเดท Common Table Expressions (WITH)
- อัพเดท Window Functions
🤩 Future Improvement
1
Important Note
😊 นักเรียนทีซือหนังสือเล่มนีจะได้รับการอัพเดท/ ปรับปรุงเนือหาใหม่ทีแอดได้รับจาก
feebdack ของผู้อ่าน ถ้าใครมีคอมเม้นต์/ feedback สามารถติดต่อแอดสองช่องทาง
toy@datarockie.com หรือทางเฟซบุ๊ค m.me/datarockie
ขอบคุณทุกคนทีเลือกและให้โอกาสหนังสือเล่มนี แอดหวังว่าหนังสือเล่มนีจะช่วยให้ทุกคนเข้าใกล้
ความฝนของตัวเองอีกก้าวหนึง ไม่ว่าฝนนันจะเปนอะไรก็ตาม
2
“ If there's a book that you want to read, but it hasn't been
written yet, then you must write it.”
ถ้ามีหนังสือทีเราอยากอ่าน แต่ยังไม่มีใครเขียนมันขึนมา เราก็ต้องเขียนมันขึนมาเอง
Toni Morisson
3
CONTENT
1. Why Learn SQL?
2. Download Software
a. DB Browser for SQLite
b. Sublime (Free text editor)
3. Understanding The ER Diagram
4. Connect to Database
5. Five Minutes Quick Start Guide
6. SELECT
a. SELECT *
b. SELECT columns
c. LIMIT
d. DISTINCT
e. Create new column
f. Rename column using AS (alias)
7. WHERE
a. Boolean Operator
b. IN
c. BETWEEN AND
d. LIKE
e. IS NULL
f. NOT
g. Regular Expressions
8. When SQL meets Excel
a. Basic Pivot Table
9. Basic SQL Functions
a. Aggregate Functions
b. Value Functions
10. GROUP BY
a. One column
b. Two or more columns
11. HAVING
a. HAVING vs. WHERE
12. ORDER BY
a. Ascending/ Descending Order
b. One column
c. Two or more columns
13. JOIN
a. INNER JOIN
b. LEFT JOIN
4
c. FULL JOIN
d. CROSS JOIN
e. SELF JOIN
f. Join tables using WHERE clause
g. UNION
14. CREATE TABLE/ VIEW
a. CREATE TABLE manually
b. CREATE TABLE using SELECT
c. DROP TABLE
d. CREATE VIEW
e. DROP VIEW
15. Import CSV File to Database
16. CASE
a. Basic CASE
b. Combine CASE with Aggregate Functions
17. CAST
18. Subqueries
a. In WHERE clause
b. In FROM clause
c. In SELECT clause
19. Common Table Expression (WITH)
20. Window Functions
a. row_number()
b. aggregate function + over()
5
สัญลักษณ์ทเราใช้
ี ในหนังสือเล่มนี
บทความหรือตัวอย่างเพิมเติมบนเว็บไซต์ทีเราคัดสรรมาให้แล้ว
HAVING ฟลเตอร์กลุ่มทีต้องการ
LIMIT กําหนดจํานวนแถวทีต้องการ
6
Chapter 1 - Why Learn SQL
Kaggle ได้ทําแบบสํารวจ The State of ML and Data Science ในป 2017 ได้รับการตอบรับจาก
data professionals จํานวน 16,000 คนทัวโลก ผลสํารวจพบว่าเครืองมือทีคนใช้กันทุกวันสาม
อันดับแรกคือ Python 76.3% R 59.2% และ SQL 53.6% ตามลําดับ
7
ถามว่า Excel ยังติดอยูใ่ น list นีไหม ติด! แต่ว่าตกไปอยูอ
่ ันดับที 15 มีคนใช้น้อยกว่า 15% ข้อมูล
นีให้ insight เราสองอย่าง
1.3 ครังแรกทีแอดรูจ
้ ัก SQL
สัมภาษณ์งาน Facebook คือจุดเริมต้นให้แอดเริมศึกษา SQL
8
ก่อนสัมภาษณ์งาน บอกตรงๆเลยว่าแอดเขียนไม่เปนเลย ตอนนันรีบไปลงคอร์สออนไลน์หลายๆ
ตัว อย่าง SQL for Data Science ของ coursera และคอร์ส SQL ของ Jose Portilla บน Udemy
SQL ย่อมาจาก Structured Query Language พัฒนาโดย IBM ตังแต่ยุค 1970s (ใช้กันมาเกือบ
50 ปแล้ว) เปนภาษาทางการทีเราใช้ทํางานกับ Relational Databases ทัวโลก
Query (verb) แปลว่าการตังคําถาม
9
ถ้าเราเขียน SQL เปน เราจะสามารถตอบคําถามทาง business ได้เกือบทังหมดเลย (ถ้าเรามีการ
เก็บข้อมูลเรืองนันๆไว้แล้ว) และปกติ CEO บริษัทชอบคนทีตอบคําถามแกได้ ว่ามัย? 😜
1.5 ตัวอย่างของ SQL query
อ้างอิงจากเว็บไซต์ payscale (2019) เงินเดือนเฉลีย i.e. median salary ของ data analyst ใน
ประเทศไทยอยูท
่ ี 360,000 บาทต่อป (เฉลียเดือนละ 30,000 บาท) และสูงสุดประมาณ 2.0 ล้าน
บาทต่อป (เฉลียเดือนละ 160,000 บาท)
ทีมา https://www.payscale.com/research/TH/Job=Data_Analyst/Salary
10
1.7 เทคนิคการเรียน SQL ให้เปนเร็วๆ
แอดก็อยากให้มันมีทางลัดเหมือนกัน แต่ความจริงคือไม่มท
ี างลัดในการเรียนหรอก วิธีเดียวทีจะ
เขียน SQL ให้เปนเร็วๆ คือลงมือเขียนมันด้วยตัวเอง แล้วอีกอย่างคือ อะไรทีมันได้มาง่ายๆ มันไม่
ค่อยมีความหมายกับชีวิตเท่าไหร่หรอก ว่ามัย?
ถ้าอยากจะเก่งกว่านี ก็ต้องเริมทําอะไรทีอยูน
่ อก comfort zone ของตัวเองบ้าง หนังสือเล่มนีจะ
พาทุกคนออกจาก comfort zone เอง 555+
SQL สําหรับงาน data analyst จริงๆแบ่งได้เปนสามระดับเอง
11
Chapter 2 - Download Software
1. เข้าไปทีเว็บไซต์ https://sqlitebrowser.org/
2. คลิกทีลิง Download
เข้าไปทีเว็บไซต์ sqlitebrowser เพือดาวน์โหลดโปรแกรมฟรี
12
ดาวน์โหลดตัว installer ทีเหมาะสมกับระบบปฏิบต
ั ิการของคอมพิวเตอร์ทีใช้
ติดตังโปรแกรมตามปกติ
รูปไอคอนของโปรแกรม DB Browser
13
หน้าตา interface ของ DB Browser สําหรับเขียน SQL
14
ตัวอย่างการเขียน SQL query ในโปรแกรม Sublime
15
Chapter 3 - Understanding The ER Diagram
ER Diagram ของ chinook database
16
● “Relationship” หรือความสัมพันธ์ของแต่ละ entity ถูกแสดงด้วยเส้นสีดํา ทีลากเชือม
ตารางต่างๆเข้าด้วยกัน
customers table มีคอลัมน์ customerid เปน primary key
สังเกตในแต่ละตารางจะมีคอลัมน์หนึงทีมีไอคอนแม่กุญแจสีเหลืองอยู่ โดยคอลัมน์เหล่านีถูก
เรียกว่า “Primary Key” ลักษณะสําคัญของ primary key คือ value ในคอลัมน์นีจะไม่ซากันเลย
เหมือนเลขบัตรประชาชน เช่น 001, 002, 003, 004, …
17
3.2 ตัวอย่างข้อมูลใน customers table
1. one to one
2. one to many
3. many to many
รูปแบบความสัมพันธ์ทีใช้เยอะทีสุดใน database คือ one to many
18
ตรงไปตรงมา เช่น ศิลปนหนึงคนหรือวง (one) สามารถมีได้มากกว่าหนึงอัลบัม (many) และหนึง
อัลบัม (one) สามารถมีได้มากกว่าหนึงเพลง (many) เปนต้น
รูปแบบความสัมพันธ์ทังหมดของ chinook database
19
Chapter 4 - Connect to Database
คลิก Open Database เพือ connect database
20
หน้าต่าง Database Structure
หน้าต่าง Browse Data
21
หน้าต่าง Execute SQL
ผลลัพธ์จะแสดงในหน้าต่างกลาง เราเรียกข้อมูลทีถูกดึงขึนมาว่า Result Set
22
Chapter 5 - Five Minutes Quick Start Guide
-- lower case
select firstname, lastname from customers;
-- upper case
SELECT FIRSTNAME, LASTNAME FROM CUSTOMERS;
-- good practice
SELECT firstname, lastname FROM customers;
23
Query นีอ่านว่า “จงเลือกคอลัมน์ firstname และ lastname ของลูกค้าจากตาราง customers”
Result set ทีได้จาก query ด้านบน
SELECT
firstname,
lastname,
country
FROM customers
WHERE country = 'USA';
24
SELECT
firstname,
lastname,
country
FROM customers
WHERE country = 'USA'
LIMIT 10;
ดึงรายชือลูกค้าจากประเทศอเมริกา 10 คนแรก (LIMIT 10)
25
ข้อดีของ single-line comment คือเราสามารถ comment โค้ดบางบรรทัดของเราได้ เพือ
ทดลองรัน query เร็วๆ ตัวอย่างด้านล่างยังสามารถรันได้ปกติ ดึงคอลัมน์ firstname, country
จากตาราง customers ดึงเฉพาะ 10 แถวแรกสุด
Result set จาก query ด้านบน
/*
SELECT
firstname,
lastname,
country
FROM customers
WHERE country = 'USA'
LIMIT 10;
*/
ตืนเต้นมัย? ตืนเต้นก็ดีแล้ว! เพราะบทต่อไป ทุกคนจะได้เรียนวิธีการเขียน SQL query ทีใช้บอ
่ ย
ทีสุดสําหรับงาน data analyst/ data science นันคือ SELECT clause แบบเจาะลึกทุก details
26
Chapter 6 - SELECT
6.1 ดึงข้อมูลทุกคอลัมน์
Query ทีเขียนบ่อยทีสุดคือ SELECT * FROM table_name; โดย * แปลว่า “all columns” query
ด้านล่างเราดึงทุกคอลัมน์ของตาราง customers
27
6.2 ดึงข้อมูลเฉพาะคอลัมน์ทเราต้
ี องการ
SELECT
firstname,
lastname,
country,
email
FROM customers;
SELECT
firstname,
lastname,
country,
email
FROM customers
LIMIT 10;
28
6.5 Merge คอลัมน์แบบ Text เข้าด้วยกัน
Query นีเรา merge คอลัมน์ firstname และ lastname โดยเราเพิมช่องว่างหรือ white space
ขันกลางระหว่างชือกับนามสกุล ใน SQL เราใช้ single quote ' ' เพือกําหนด white space
ตามตัวอย่างด้านล่าง
SELECT
firstname,
lastname,
firstname || ' ' || lastname
FROM customers;
merge columns ด้วยสัญลักษณ์ pipe || ให้ได้ full name
SELECT
firstname,
lastname,
firstname || ' ' || lastname AS fullname
FROM customers;
29
ตังชือคอลัมน์ใหม่ด้วย AS (Alias)
SELECT 8 + 2;
SELECT 8 - 2;
SELECT 8 * 2;
SELECT 8 / 2;
เราเปลียน bytes เปน megabytes ด้วยสูตร: bytes/ 1048576.0 และเปลียน milliseconds เปน
minutes ด้วยสูตร: milliseconds/ 60000.0 ตามลําดับ
SELECT
name,
bytes/ (1024.0 * 1024.0) A S mb,
milliseconds/ 60000.0 AS minutes
FROM tracks;
30
transform สร้างสองคอลัมน์ใหม่คือ mb และ minutes ตามลําดับ
31
Chapter 7 - WHERE
เราจะเขียน WHERE clause ต่อท้าย SELECT clause เสมอ ตัวอย่าง query ด้านล่างฟลเตอร์
ลูกค้าทีอยูใ่ นประเทศอเมริกาเท่านัน
SELECT * FROM c
ustomers
WHERE country <> 'USA';
32
7.2 การเขียนมากกว่าหนึงเงือนไขด้วย AND/ OR
SELECT * FROM c
ustomers
WHERE country = 'USA' AND state = 'CA';
ลูกค้าต้องอยูใ่ นประเทศอเมริกาและรัฐ CA เท่านัน (สองเงือนไขเปนจริงทังคู่)
SELECT * FROM c
ustomers
WHERE country = 'USA' OR country = 'France' OR country = 'Belgium';
SELECT
firstname,
lastname,
email,
country
FROM customers
WHERE (country = 'USA' OR country = '
France')
AND (email = 'fharris@google.com' O R email =
'marc.dubois@hotmail.com');
33
มีลก
ู ค้าแค่สองคนทีตรงกับเงือนไขทีเราเขียน
SELECT * FROM c
ustomers
WHERE country I N ('USA', 'France', 'Belgium');
34
Query สุดท้ายของหัวข้อ BETWEEN AND แอดเขียนตัวอย่างการฟลเตอร์ข้อมูลในคอลัมน์แบบ
text เช่น billingcountry โดย query นีจะฟลเตอร์ชือประเทศทีขึนต้นด้วยอักษร A ไปจนถึง B
(exclusive แบบปลายเปดจะไม่รวม C)
Result set จะดึงข้อมูลเฉพาะประเทศทีชือขึนต้นด้วยตัว A, B
ฟลเตอร์เฉพาะ record ที company เปนค่า NULL
35
7.6 การเขียนเงือนไขด้วย NOT
เราสามารถใช้ NOT operator เพือกลับค่า TRUE/ FALSE ของเงือนไขใน WHERE clause ได้
ง่ายๆ ตัวอย่างเช่น การเปลียนเงือนไขจาก IS NULL เปน IS NOT NULL
SELECT * FROM c
ustomers
WHERE company I S NOT NULL;
ฟลเตอร์เฉพาะ record ที company ไม่ใช่ค่า NULL (ลองเปรียบเทียบกับ query ก่อนหน้า)
นักเรียนสามารถใช้ NOT ได้กับทุก operators ทีแอดสอนมาในบทนี เช่น NOT IN, NOT LIKE,
NOT BETWEEN AND รวมถึง NOT = หรือ NOT >= ก็ได้ ลองดูตัวอย่าง queries ด้านล่าง
-- not and in
SELECT * FROM c
ustomers
WHERE country N OT IN ('USA', 'France', 'Belgium');
36
7.7 การเขียนเงือนไขแบบ pattern matching
ฟลเตอร์เฉพาะเบอร์โทรทีมีเลข 555
LIKE หา pattern แบบ case-insensitive แปลว่า 'L%' กับ 'l%' จะหา pattern เดียวกันคือ
ชือขึนต้นด้วยตัว L ไม่สนว่าเปน uppercase หรือ lowercase
37
7.8 การเขียน Regular Expressions
ดึงชือ firstname ทีมีตัว h อยูด
่ ้วย
่ ้วย REGEXP ค้นหา pattern แบบ case-sensitive
ดึงชือ firstname ทีมีตัว H อยูด
38
แอดสรุปรูปแบบของ Regular Expressions ทีเราใช้บอ
่ ยๆในตารางด้านล่าง
^A ขึนต้นด้วยตัวอักษร A
A$ ลงท้ายด้วยตัวอักษร A
1. ฟลเตอร์ชือจริงลูกค้าทีขึนต้นด้วยตัวอักษร L
ลูกค้าทีชือขึนต้นด้วยตัว L มีทังหมด 5 คน
39
ลูกค้าทีชือขึนต้นด้วยตัว L หรือ A มีทังหมด 8 คน
3. ฟลเตอร์ชือลูกค้าทีลงท้ายด้วยตัวอักษร a
ลูกค้าทีชือ firstname ลงท้ายด้วยตัว a มีทังหมด 8 คน
ลูกค้าทีมี postalcode เปนตัวเลขอย่างน้อยหนึงตัวมีทังหมด 55 คน
40
5. ฟลเตอร์ postalcode ทีเปนตัวเลข digit 5 ตัวติดกัน - pattern นีจะค่อนข้างซัอนนิด
หน่อย เพราะเราใส่ {5} เข้ามาด้วย เพือกําหนดจํานวนตัวเลขทีเราต้องการ เช่น 5 หลัก
ลูกค้าทีมี postalcode เปนตัวเลข 5 ตัวติดกันมีทังหมด 23 คน
41
ไม่ธรรมดา!
Achievement I Unlocked
ยินดีด้วย ตอนนีทุกคนจบ Foundations พืนฐานการเขียน SQL แล้ว
42
Chapter 8 - When SQL meets Excel
SELECT
A.trackid,
A.name,
A.composer,
A.milliseconds,
A.bytes,
A.unitprice,
B.name AS genreName
FROM tracks AS A
JOIN genres AS B ON A.genreid = B.genreid;
Note - ตอนนียังไม่จําเปนต้องเข้าใจการทํางานของ query ด้านบน ให้ลองรันเฉยๆก่อน
43
คลิกทีไอคอน เลือก Export to CSV และ Save File ไว้บนหน้าจอ Desktop ของนักเรียนได้
เลย DB Browser จะ Export Result Set ออกมาเปน CSV file (Comma-Separated Value) นัก
วิเคราะห์นิยมเปดไฟล์ประเภทนีด้วยโปรแกรม Excel หรือ Text Editor ทัวไป
คลิกทีไอคอนด้านบนเพือ Export to CSV
หน้าตาของ CSV file ทีเรา Export ออกมา (เหมือนกับไฟล์ Excel ทัวไป)
44
8.4 วิธก
ี ารหมุนข้อมูลด้วย Pivot Table
คลิกทีแท๊บ Insert เลือก Pivot Table
คลิก OK ได้เลย
ใช้เม้าส์ลากคอลัมน์ไปวางใน field ตามรูปนี
45
Pivot Table จะสร้างรายงาน (report) ทางด้านซ้ายมือของหน้าจอ เปนรายงานทีนับจํานวน
เพลงในแต่ละ genre จากรูปเราสามารถสรุป insight แบบเร็วๆ ได้ดังนี
้ มูลหา Insight ได้อย่างรวดเร็ว
Pivot Table ช่วยให้เราวิเคราะห์ขอ
เราสามารถ Sort Rows ใน Pivot Table ได้ปกติ เหมือนกับใช้งาน Excel Table ทัวไปเลย
46
Chapter 9 - SQL Functions
SELECT
AVG(bytes),
SUM(bytes),
MIN(bytes),
MAX(bytes),
COUNT(bytes)
FROM tracks;
Result set ของ aggregate functions
แอดเขียนสรุปวิธีการใช้งานของแต่ละฟงชันในตารางด้านล่าง
AVG หาค่าเฉลีย
SUM หาผลรวม
MIN หาค่าตาทีสุด
MAX หาค่าสูงทีสุด
47
9.2 ตังชือผลลัพธ์ของ Aggregate Functions
SELECT
AVG(bytes) AS avg_bytes,
SUM(bytes) AS sum_bytes,
MIN(bytes) AS min_bytes,
MAX(bytes) AS max_bytes,
COUNT(bytes) AS count_bytes
FROM tracks;
เปลียนชือคอลัมน์ใหม่
SELECT
COUNT(*),
COUNT(company)
FROM customers;
48
● 59 คือจํานวน records ทังหมดของ customers table
● 10 คือจํานวน completed records (NOT NULL) ของคอลัมน์ company
ถ้าเราลอง query คอลัมน์ company ขึนมาดูจะเห็นค่า NULL หลายแถวเลย
SELECT
firstname,
UPPER(firstname) AS upperName,
LOWER(firstname) AS lowerName,
SUBSTR(firstname, 1, 3) AS shortName
FROM customers;
49
query นีเราใช้ value functions ปรับชือจริง ให้เปนตัวพิมพ์ใหญ่ ตัวพิมพ์เล็ก และ substr() ตัวอักษรที 1-3 ตามลําดับ
SELECT
AVG(bytes),
ROUND(AVG(bytes), 2) AS roundMeanByte
FROM tracks;
9.6 วิธจ
ี ัดการค่า NULL (missing values)
ค่า NULL เปรียบเสมือน missing values ใน SQL database ถ้าคอลัมน์ไหนมีค่า NULL เรา
สามารถใช้ฟงชัน COALESCE() เพือแทนทีค่า NULL ได้ง่ายๆ ตัวอย่าง query ด้านล่าง เราใช้
COALESCE() เพือแทนทีค่า NULL ในคอลัมน์ company ด้วยคําว่า 'End Customer'
50
SELECT
company,
COALESCE(company, 'End Customer') AS cleanCompany
FROM customers;
SELECT DATE('now');
พรีวิวคอลัมน์ invoicedate ใน invoices table
51
Data analyst นิยมใช้ฟงชัน STRFTIME() เพือปรับ format ของคอลัมน์ datetime ใน SQL
database ตัวอย่าง query ด้านล่าง เราปรับ format ของคอลัมน์ invoicedate ให้แสดงเฉพาะป
(%Y) เดือน (%m) และวันที (%d) ตังชือคอลัมน์ใหม่ว่า year, month, day ตามลําดับ
SELECT
invoicedate,
STRFTIME('%Y', invoicedate) AS year,
STRFTIME('%m', invoicedate) A S month,
STRFTIME('%d', invoicedate) A S day
FROM invoices;
9.8 วิธก
ี ารใช้งาน value functions ใน WHERE clause
52
SELECT firstname, lastname, country
FROM customers
WHERE UPPER(country) = 'UNITED KINGDOM';
ถ้าเราใช้ upper() มาช่วยเขียนเงือนไข ก็จะสามารถดึง United Kingdom ออกมาได้ทังหมด
ROUND ปรับจํานวนทศนิยม
53
Chapter 10 - GROUP BY
1. เราใช้ GROUP BY คู่กับ Aggregate Functions เสมอ (avg, sum, min, max, count)
2. ทุกคอลัมน์ทีอยูใ่ น SELECT clause ทีไม่ใช่ aggregate functions ต้องอยูใ่ น GROUP BY
clause เสมอ หรืออธิบายอีกแบบคือ คอลัมน์ไหนทีอยูใ่ น GROUP BY clause ต้องอยูใ่ น
SELECT clause เสมอเช่นกัน
10.1 การจับกลุ่มแบบหนึงคอลัมน์
SELECT COUNT(*)
FROM customers;
SELECT
country,
COUNT(*) AS n
FROM customers
GROUP BY country;
54
Result set ทีได้จาก GROUP BY country
10.2 การจับกลุ่มแบบมากกว่าหนึงคอลัมน์
SELECT
country,
state,
COUNT(*) AS n
FROM customers
GROUP BY country, state;
ข้อดีของ GROUP BY คือเราไม่จําเปนต้องเขียนชือคอลัมน์แบบเต็มๆก็ได้ แต่เขียนเปน column
index เช่น 1, 2 แทน ตามตัวอย่างด้านล่าง โดยที 1 คือตําแหน่งของคอลัมน์ country และ 2 คือ
ตําแหน่งของคอลัมน์ state ใน Result Set ล
องวิเคราะห์ผลลัพธ์ทีได้จาก query นีด้านล่าง
SELECT
country,
state,
COUNT(*) AS n
FROM customers
GROUP BY 1, 2;
55
Result set ทีได้จาก GROUP BY country, state
56
Chapter 11 - HAVING
SELECT
country,
COUNT(*) AS n
FROM customers
GROUP BY country
HAVING n >= 5;
มีแค่ 4 ประเทศทีมีลก
ู ค้า >=5 คนขึนไป
มาลองดูอีกหนึง query ต่อยอดจากเมือกี คราวนีเราเพิมเงือนไขฟลเตอร์คือ “ประเทศทีมีลูกค้า
มากกว่าหรือเท่ากับ 5 คนขึนไป และต้องไม่ใช่ประเทศอเมริกา”
SELECT
country,
COUNT(*) AS n
FROM customers
GROUP BY country
HAVING n >= 5 AND country <> 'USA';
57
ตอนนี result set เหลือแค่สามประเทศเท่านัน
SELECT
country,
COUNT(*) AS n
FROM customers
WHERE country <> 'USA'
GROUP BY country
HAVING n >= 5;
58
Chapter 12 - ORDER BY
SELECT
firstname,
country
FROM customers
ORDER BY firstname;
เรียงชือจริงลูกค้าจาก A ไป Z
SELECT
firstname,
country
FROM customers
ORDER BY firstname DESC;
59
12.3 เรียงข้อมูลมากกว่าหนึงคอลัมน์
SELECT
firstname,
country
FROM customers
ORDER BY country, firstname;
SELECT
firstname,
country
FROM customers
ORDER BY 2, 1;
ถ้าต้องการเรียงข้อมูลแบบ descending order แค่ใส่ keyword DESC ต่อท้าย column index ได้
เลย ทําไมมันง่ายอย่างนี 😜
SELECT
firstname,
country
FROM customers
ORDER BY 2 DESC, 1 DESC;
60
Chapter 13 - JOIN
ER Diagram ของ chinook database
มาทบทวนเนือหาในบทที 3 กันนิดนึง
แต่ถ้า Primary Key หรือตัวย่อ PK ของ artists table (คอลัมน์ artistid) ไปโผล่อยูใ่ น tables
อืนๆ เช่น albums เราจะเรียกคอลัมน์นีว่า Foreign Key หรือตัวย่อ FK ล
องดูตัวอย่างต่อไปนี
61
ER diagram ของ tables: artists, albums และ tracks พร้อม PK และ FK
62
คอลัมน์ artistid สามารถมีค่าซากันได้ใน table albums
63
13.3 วิธก
ี ารเขียน JOIN (syntax)
SELECT
t1.column,
t2.column
FROM t1 JOIN t2 ON t1.PK = t2.FK;
● t1 และ t2 คือชือ tables ทีเรานํามา JOIN กัน
● วิธีการเขียนดึงคอลัมน์ใน SELECT clause เราใช้ syntax: table.column_name
● ON t1.PK = t2.FK คือเงือนไขในการ JOIN สองตารางนีเข้าด้วยกัน ซึงก็คือ PK=FK
ตัวอย่าง result set ของ inner join
64
มาลองดูตัวอย่าง query จริงๆกันบ้าง เรากลับมาที chinook database ปกติแอดจะเขียน JOIN
clause กับ ON clause คนละบรรทัด จะได้อ่าน query ง่ายๆ สังเกตวิธีการเขียนชือ
table.column_name ใน SELECT clause
SELECT
artists.artistid,
artists.name,
albums.title
FROM artists
INNER JOIN albums
ON artists.artistid = albums.artistid;
SELECT
A.artistid,
A.name AS artistName,
B.title AS albumName
FROM artists AS A
INNER JOIN albums AS B
ON A.artistid = B.artistid;
65
13.5 LEFT JOIN
LEFT JOIN จะแตกต่างจาก INNER JOIN นิดเดียว ตรงที table ทางด้านซ้ายมือจะเปน table
หลักทีเรานําไป join กับ table ทางด้านขวามือ ตัวอย่างด้านล่างจะเห็นว่า result set ของ LEFT
JOIN จะมีโอกาสเกิดค่า NULL ในแถวที ID ของทังสองตารางไม่สามารถ match กันได้
ตัวอย่าง result set ของ left join ค่า NULL แสดงใน rows ID = 4 และ 5
Query ของ LEFT JOIN หน้าตาเหมือนกับ INNER JOIN เลย แค่เปลียนจากคําว่า INNER เปน
LEFT เท่านีก็เสร็จเรียบร้อย
SELECT
A.artistid,
A.name AS artistName,
B.title AS albumName
FROM artists AS A
LEFT JOIN albums AS B
ON A.artistid = B.artistid;
ผลลัพธ์ทีได้จาก left join query
66
สําหรับ RIGHT JOIN จริงๆไม่ต้องเรียนก็ได้ เพราะว่าแค่เราสลับตําแหน่ง tables ใน LEFT
JOIN query (เปลียนลําดับของ A กับ B ใน syntax) ก็เทียบเท่ากับการเขียน RIGHT JOIN แล้ว
FULL JOIN เปนรูปแบบการ join tables ทีใช้น้อยทีสุด เพราะว่า result set ของเราจะออกมา
ขนาดใหญ่มาก query ทีเขียนด้วย full join จะดึงมาหมดเลยทุก records ทัง table ซ้ายและขวา
ทีอยูใ่ น query ถึงแม้ว่า PK จะไม่สามารถ match กับ FK ได้ก็ตาม (แสดงเปนค่า NULL)
ตัวอย่าง result set ของ full join
Syntax ของ full join เขียนเหมือนกับ inner และ left join เลย ตัวอย่าง query นีแอดเขียน A.*,
B.* ใน SELECT clause เพือดึงทุกคอลัมน์ของทังสองตารางออกมาใน result set
SELECT
A.*,
B.*
FROM artists AS A
FULL JOIN albums AS B
ON A.artistid = B.artistid;
67
ยิงเขียน join หลายๆตาราง เรายิงต้องระมัดระวังเรืองการพิมพ์ชือคอลัมน์และชือตาราง
ทังหมด เพราะจะมีโอกาสผิดง่าย วิธีแก้คือต้องฝกเขียนบ่อยๆ ทําความเข้าใจ database ถ้าได้
เขียนทุกวันแล้วมือของเราจะคล่องขึน
ER diagram ของ tables: artists, albums, tracks
68
ยาอีกครัง การเขียน JOIN ก็คือการเขียนเชือมตารางด้วย PK = FK เมือ join tables ที
ต้องการเสร็จแล้ว เราสามารถฟลเตอร์ result set ด้วย WHERE clause หรือจะใช้ GROUP BY,
HAVING, ORDER BY หรือ LIMIT ทุกอย่างทีเราเรียนมาในบทก่อนหน้าได้หมดเลย
Cartesian Join คือการจับทุก rows ของสองตารางมาชนกันหมดเลย (3 x 2 = 6 rows)
69
จํานวน rows ของ result set (95425) เกิดจากจํานวน row ของทังสองตารางมาคูณกัน
70
เราจะเขียน self join โดยใช้คอลัมน์ reportsto และ employeeid เปนเงือนไขการ join
SELECT
t1.firstname AS employee,
t2.firstname AS lineManager
FROM employees AS t1
LEFT JOIN employees AS t2
ON t1.reportsto = t2.employeeid;
Result set ทีได้จาก self join query
71
Andrew เปนคนเดียวทีไม่มี line manager (NULL) i.e. ตําแหน่ง general manager น่าจะสูง
กว่าคนอืน Andrew มีลูกน้องสองคนคือ Michael และ Nancy ส่วนคนทีมีลูกน้องมากทีสุดคือ
Nancy ทีมีลูกน้องสามคนคือ Jane, Margaret และ Steve
ความยืดหยุน
่ ของ SQL ทําให้เราสามารถเขียน inner join query ด้วย WHERE clause ได้เหมือน
กัน ลองรันสอง queries ด้านล่างทีละคิวรี และพิจารณา result set ทีได้ ทังสอง query ต้องได้
จํานวน rows เท่ากันที 347 rows
ผลลัพธ์ทีได้จากการเขียน inner join ด้วย where clause
13.12 UNION
UNION คือการนํา result set ของสอง queries มาเรียงต่อกัน (แบบ rows stacking) โดยทังสอง
queries ต้องมีจํานวนคอลัมน์เท่ากัน และ data type ของคอลัมน์ต้องเหมือนกันด้วย
72
diagram แสดงการผลลัพธ์ของการ UNION
UNION
ORDER BY country;
Result set ทีได้จากการ UNION สอง queries เข้าด้วยกัน
73
13.13 เทคนิคการเขียน JOIN ในชีวิตจริง
-- with AS
SELECT
A.artistid,
A.name AS artistName,
B.title AS albumName,
C.name AS trackName,
C.bytes,
C.milliseconds,
C.unitprice
FROM artists AS A
INNER JOIN albums AS B ON A
.artistid = B.artistid
INNER JOIN tracks AS C ON B .albumid = C.albumid;
ส่วน query ด้านล่าง แอดลบ AS ทิงไปแล้ว ใช้เปนเคาะ space bar หนึงครังแทน (white space)
-- without AS
SELECT
A.artistid,
A.name artistName,
B.title albumName,
C.name trackName,
C.bytes,
C.milliseconds,
C.unitprice
FROM artists A
INNER JOIN albums B ON A
.artistid = B.artistid
INNER JOIN tracks C ON B .albumid = C.albumid;
ส่วนตัวแอดยังแนะนําให้นักเรียนทุกคนเขียน AS โดยเฉพาะเวลาเปลียนชือคอลัมน์ใน
SELECT clause เวลาเราเขียน AS ใน query จะช่วยให้โค้ดเราอ่านง่ายขึน i.e. more readable
74
13.14 สรุปเนือหาสําคัญของการ JOIN รูปแบบต่างๆ
1. รูปแบบการ join ทังหมดทีเราเรียนในบทนี: inner, left (right), full, cross และ self-join
2. เราใช้ primary key และ foreign key ในการเชือม tables ต่างๆเข้าด้วยกัน
3. มากกว่า 90% ของการเขียน join ด้วย SQL คือ inner และ left join
4. Inner Join จะ return result set เฉพาะ rows ทีสามารถ match กันได้เท่านัน (overlap)
5. Left Join ใช้ตารางซ้ายมือเปนตารางหลักในการ join ถ้า primary key สามารถ match
กับ foreign key ได้ ผลลัพธ์ก็ดึงออกมาตามปกติ แต่ถ้า rows ไหน match กันไม่ได้ result
set จะแสดงค่า NULL
6. UNION ใช้ทํา row stacking นําผลลัพธ์ของสอง queries (หรือมากกว่านัน) มาเรียงต่อ
กัน โดย result set ของแต่ละ query ต้องมีจํานวนคอลัมน์เท่ากัน และมี data type ของ
คอลัมน์เหมือนกันด้วย
75
สุดยอด!
Achievement II Unlocked
ยินดีด้วย ตอนนีทุกคนจบระดับ Intermediate การเขียน SQL ขันกลางแล้ว
76
Chapter 14 - CREATE TABLE/ VIEW
Query แรกคือการสร้าง blank table ชือว่า t1 ด้วย CREATE TABLE clause ตารางนีมีทังหมด 4
คอลัมน์คือ id, nickname, email และ income ตามลําดับ เราสามารถกําหนด data type ของ
แต่ละคอลัมน์ด้วย keyword INT, NUMERIC หรือ TEXT
77
Query ทีสองคือการใส่ข้อมูลเข้าไปที table t1 (ใส่ทีละแถว) ด้วย INSERT INTO clause โดย
query นีจะมีวิธีการเขียนแบบนี
เมือสร้าง table เสร็จแล้ว เราสามารถ query ข้อมูลด้วย SELECT clause ปกติได้เลย จบวิธีแรก!
table ใหม่ทีเราสร้างขึนมา เรา insert ข้อมูลไปทังหมด 5 rows
วิธีทีสอง ทีเราน่าจะได้ใช้บอ
่ ยกว่า คือการเขียน CREATE TABLE กับ SELECT clause เพือดึง
ข้อมูลมาจาก tables อืนๆทีอยูใ่ น database วิธีนีแอดว่าใช้ง่ายกว่าแบบแรก ตัวอย่าง query ด้าน
ล่างใช้สร้าง table t2 ทีดึงข้อมูลจาก artists และ albums (inner join)
78
14.3 วิธก
ี ารลบ table
14.4 วิธส
ี ร้าง Virtual Table หรือ VIEW
Virtual Table หรือเรียกสันๆว่า “VIEW” คือ result set ของ query ทีเราเขียน ความแตกต่าง
ของ view กับ (physical) table จริงๆคือ view ถูกสร้างขึนมา on top tables อีกครังหนึง ถ้า
ข้อมูลใน tables จริงมีการเปลียนแปลง ข้อมูลทีเราเห็นใน view ก็จะถูกอัพเดทเช่นกัน
Syntax สําหรับการสร้าง view จะคล้ายกับ table เลย ตัวอย่าง query นีเราใช้ CREATE VIEW
เพือสร้าง view ลูกค้าแบบ corporate (i.e. company is not null)
79
Chapter 15 - Import CSV File to Database
CSV ย่อมาจาก comma-separated values file เปน flat file (หรือ text-based) ทีไม่ได้ม ี
format อะไรเปนพิเศษ data analyst นิยมแชร์ไฟล์แบบนีหากัน เพราะว่าไฟล์จะมีขนาดเล็ก
และสามารถเปดได้ด้วยโปรแกรม Excel/ text editor
ตัวอย่างไฟล์ CSV ทีเราจะ import เข้า chinook.db ด้วยโปรแกรม DB Browser
คลิกที File > Import > Table from CSV file
80
2. Browser หาไฟล์ CSV ทีต้องการ import เข้าสูฐ
่ านข้อมูล แล้วคลิก Open
เลือกไฟล์ csv ทีต้องการ
ตังชือ table ใหม่ทีช่อง Table name เสร็จแล้วคลิก OK
เราสามารถ query ข้อมูลใน table ใหม่ได้ปกติเลย หรือถ้าไม่ต้องการ table นีแล้ว พิมพ์ DROP
TABLE ตามด้วยชือ table ทีต้องการเอาออก (ลบ) จาก database
81
Chapter 16 - CASE
วิธีการจํา syntax ของ CASE ให้จําว่า: CASE WHEN THEN ELSE END ตามลําดับ ลองดู
ตัวอย่างในบทนีแล้วจะเข้าใจขึน query อาจจะดูยาว แต่ง่ายกว่าทีหลายคนคิด
SELECT
company,
CASE
WHEN company IS NULL HEN 'end customers'
T
WHEN company IS NOT NULL THEN 'corporate'
END AS segment
FROM customers;
82
แอดแนะนําให้ตังชือคอลัมน์ของ CASE เสมอ โดยใช้ AS หลังจาก END keyword
Rows ไหนเปนค่า NULL คอลัมน์ segment จะขึนเปนคําว่า end customers
SELECT
company,
CASE
WHEN company IS NULL THEN 'end customers'
ELSE 'corporate'
END AS segment
FROM customers;
16.2 วิธเี ขียน CASE แบบมากกว่าสองเงือนไข
SELECT
total,
CASE
WHEN total >= 20 T HEN ' high value'
WHEN total >= 10 T HEN ' medium value'
ELSE 'low value'
END AS segment
FROM invoices;
83
Query นีแอดเขียนทังหมดสามเงือนไข โดยเขียนเงือนไขกับคอลัมน์ total ใน invoices table
84
เราเขียน case ร่วมกับ count เพือนับจํานวนของแต่ละ segment (ใช้รว
่ มกับ group by)
Subquery ได้ผลลัพธ์เหมือนกับหัวข้อ 16.3 แต่เราเขียนโค้ดสันลงเยอะเลย (more efficient)
85
Chapter 17 - CAST
SELECT
555, -- integer
CAST(555 A S TEXT), -- text
CAST(555 A S REAL) - real
-
;
คอลัมน์ทีเรา cast แล้ว มองเผินๆยังเหมือนกันอยู ่
SQLite มีฟงชัน TYPEOF() ทีใช้ตรวจสอบ data type ของคอลัมน์ได้ i.e. TYPEOF() คือหนึงใน
ฟงชันประเภท VALUE functions ทีเราอธิบายในบทที 9
SELECT
TYPEOF(555),
TYPEOF(CAST(555 A S T EXT)),
TYPEOF(CAST(555 A S R EAL))
;
วิธีเขียนฟงชันนีก็แค่ wrap มันไปทีคอลัมน์ทีเราต้องการได้เลย ลองดู result set ในรูปด้านล่าง
86
SQL ใช้ฟงชัน TYPEOF() เพือตรวจสอบ data type
ตัวอย่าง query ถัดไปคือการ CAST คอลัมน์ text ‘120.35’ ให้เปน real หรือ integer
SELECT
-- text, real, integer
'120.35',
CAST('120.35' AS REAL),
CAST('120.35' AS INT),
-- check data types
TYPEOF('120.35'), -- text
TYPEOF(CAST('120.35' AS R EAL)), -- real
TYPEOF(CAST('120.35' AS I NT)) -- integer
;
SELECT
total,
TYPEOF(total),
CAST(total AS TEXT),
TYPEOF(CAST(total AS TEXT))
FROM invoices;
original คอลัมน์คือ REAL แต่เรา cast ให้กลายเปน TEXT
87
Chapter 18 - Subqueries
SQL Padawans อ่านหนังสือเล่มนีจบกลายเปนเจไดพอดี 555+ (image source)
88
18.1 Inner Query อยูไ่ ด้ทไหนบ้
ี าง
Data analyst นิยมเขียน inner query สีจุดด้วยกัน (ตําแหน่ง) ได้แก่ WHERE, FROM, JOIN
และ SELECT clauses โดยตําแหน่งทีเราเจอ inner query ได้บอ
่ ยทีสุดคือใน WHERE clause
-- first step
SELECT MAX(bytes) FROM tracks; -- 1059546140
-- second step
SELECT trackid, name FROM tracks
WHERE bytes = 1059546140;
เพลงทีมีขนาดใหญ่สด
ุ ชือว่า Through a Looking Glass ขนาด 1059546140 bytes
แต่ถ้าเราเขียน subquery เปน เราก็แค่ยก first query ทีเราเขียนตะกี ไปใส่ใน WHERE clause
ได้เลย โดย first query ต้องอยูใ่ นวงเล็บเสมอ และเราเรียก query ในวงเล็บมา inner query
89
18.3 วิธเี ขียน Subquery ใน WHERE clause ด้วย IN
SELECT
customerid,
SUM(total) AS totalSpend
FROM invoices
GROUP BY 1
ORDER BY 2 DESC
LIMIT 5;
customer id ของลูกค้า 5 คนแรกทีเปน top spenders
SELECT
customerid,
firstname || ' ' || lastname AS fullName,
address,
country,
email
FROM customers
WHERE customerid IN (6, 26, 57, 45, 46);
ไม่มีอะไรผิดกับวิธีการปกติแบบนีเลย (i.e. รัน query ปกติสองรอบ) แต่ subquery สามารถรวม
สอง queries นีเข้าด้วยกันเพือรันครังเดียวจบ ได้ผลลัพธ์พร้อมใช้งานทันที
90
ผลลัพธ์ทีได้จากการรัน query ปกติสองรอบ - top 5 most spending customers
SELECT
customerid,
firstname || ' ' || lastname AS fullName,
address,
country,
email
FROM customers
WHERE customerid IN (
SELECT customerid FROM (
SELECT customerid, SUM(total) AS totalSpend
FROM invoices
GROUP BY 1
ORDER BY 2 DESC
LIMIT 5
)
);
1. Query ทีหนึง (สีเหลือง) ใช้หา customerid และ totalSpend ของลูกค้า 5 คนทีเปน top
spenders (result set ของ query นีมีสองคอลัมน์)
2. Query ทีสอง (สีมว
่ ง) ให้ดึงคอลัมน์ customerid ออกมาแค่หนึงคอลัมน์
3. Query ทีสาม (สีขาว) ชันนอกสุดคือการดึง profile ลูกค้า โดยเราเขียน WHERE
customerid IN (6, 26, 45, 46, 57) ทีเราได้จาก inner queries ชันในทังสองอัน
เวลา SQL รัน statement นี โดยทัวไป subqueries จะเริมรันจาก inner query ชันในสุด
ก่อน แล้วค่อยๆไล่ออกมาทีชันนอกสุด ตัวอย่างนี steps การรันคือ สีเหลือง > สีมว
่ ง > สีขาว
91
18.4 วิธเี ขียน Subquery ใน FROM clause
Inner query ทีเราเขียนใน FROM clause เหมือนเอา result set ทีได้มาใช้เปน temporary
table ให้ query ชันนอกวิเคราะห์ต่อด้วย SELECT clause
ไอดีของลูกค้าทังห้าคนทีเปน top spenders
query นีเราดึงรายชือลูกค้าของประเทศอเมริกา 5 คนแรก เรียงตามนามสกุลจาก A ไป Z
92
18.5 วิธเี ขียน Subquery ใน JOIN clause
คํานวณผลรวมคอลัมน์ total จับกลุ่มตาม customer id
ขันตอนทีสอง นํา result set ทีได้ไป JOIN กับ profile ของลูกค้าใน customers table และดึง
full name ออกมาด้วย query นี (เขียนแบบ subquery สบายๆ)
SELECT
A.customerid,
A.firstname || ' ' || A.lastname AS fullName,
B.totalSpend
FROM customers A
LEFT JOIN (
SELECT customerid, SUM(total) AS totalSpend
FROM invoices
GROUP BY 1) B
ON A.customerid = B.customerid
ORDER BY 3 DESC;
เวลาเขียน inner query ใน JOIN clause ด้วย อย่าลืมตังชือให้มันด้วย เช่น temp, B ฯลฯ
93
ผลลัพธ์ทีได้จาก subquery (left join) จะออกมาสามคอลัมน์
SELECT
customerid,
firstname || ' ' || lastname AS fullName
FROM customers;
เสร็จแล้วเราจะเขียน subquery ใน SELECT clause (ไฮไลท์สีเหลือง) เพือหาผลรวมของคอลัมน์
total ใน invoices table แอดอยากให้ทุกคนใช้เวลาสักนิดนึงเพือทําความเข้าใจ query นี
SELECT
customerid,
firstname || ' ' || lastname AS fullName,
(SELECT SUM(total) FROM invoices
WHERE customers.customerid = invoices.customerid) AS totalSpend
FROM customers
ORDER BY 3 DESC;
94
และจุดทีสําคัญมากของการเขียน subquery นีคือการเขียน WHERE customers.customerid =
invoices.customerid เ พือลิงผลรวม SUM(total) กับไอดีของลูกค้าแต่ละคนใน outer query
-- correlated subquery
SELECT
genreid,
name AS genreName,
(SELECT COUNT(*) FROM tracks
WHERE tracks.genreid = genres.genreid) AS numberOfTracks
FROM genres
ORDER BY 3 DESC;
หรือจะเขียน subquery ใน JOIN clause แบบนีก็ได้ผลลัพธ์แบบเดียวกัน
95
Result set ทีได้จาก correlated subquery/ subquery in JOIN clause เหมือนกัน
Trust me my Padawans!
96
Chapter 19 - Common Table Expressions
Query ด้านล่างเราใช้ WITH เพือสร้าง temp table ตังชือว่า tmp1 (ใช้ AS มาช่วยอีกแล้ว) เสร็จ
แล้วเขียน SELECT เพือดึงคอลัมน์ firstname และ lastname ออกมาจาก tmp1 ตามลําดับ
ผลลัพธ์ทีได้จากสอง queries ด้านบนเหมือนกัน
97
19.2 เขียน WITH เพือสร้าง temp มากกว่าหนึงตาราง
ถ้าเราใช้ WITH เราสามารถ break query นีออกเปน tmp1 และ tmp2 ตามลําดับ
WITH
tmp1 AS (
SELECT customerid, firstname, lastname
FROM customers
WHERE country = 'USA'
),
tmp2 AS (
SELECT customerid, total
FROM invoices
WHERE invoicedate BETWEEN '2010-01-01' AND '2010-01-31'
)
SELECT * FROM (
SELECT customerid, firstname, lastname
FROM customers
WHERE country = 'USA') tmp1
INNER JOIN (
SELECT customerid, total
FROM invoices
WHERE invoicedate BETWEEN '2010-01-01' AND '2010-01-31') tmp2
ON tmp1.customerid = tmp2.customerid;
98
ลูกค้าชาว USA ชือว่า Kathy Chase แค่คนเดียวทีมี invoice เกิดขึนในเดือนมกรามคม 2010
19.3 สรุปวิธก
ี ารเขียน WITH
WITH
-- first temp table
tmp1 AS (
SELECT
customerid,
firstname || ' ' || lastname AS fullName,
address,
country,
email
FROM customers),
รายชือ top 5 most spenders ของ chinook database
99
Chapter 20 - Window Functions
“A window function performs a calculation across a set of table rows that are
somehow related to the current row.”
้ ัก
20.2 Window Function แรกทีทุกคนต้องรูจ
SELECT
ROW_NUMBER() OVER() AS rowNum, -- this is your first window function
firstname || ' ' || lastname AS fullName
FROM customers;
100
row_number() ใช้สร้างคอลัมน์แบบ running number 1, 2, 3, … n ตามจํานวน rows ของ result set
เราสามารถเปลียน aggregate functions (avg, sum, min, max, count) ให้กลายเปน window
functions ถ้าเราเขียน OVER() ต่อท้ายฟงชันเหล่านี ลองดูตัวอย่างด้านล่าง
SELECT
customerid,
firstname || ' ' || lastname AS fullName,
country,
COUNT() OVER() AS Ncountry
FROM customers;
คอลัมน์ทีสีใน query นีเปลียน COUNT เปน window function (COUNT OVER) ทีนับจํานวนแถว
ทังหมดของ customers table (59 แถว) ผลลัพธ์ของ query นีอยูใ่ นหน้าถัดไป
101
คอลัมน์ Ncountry สร้างขึนจากฟงชัน count() และ over()
นิยามของ window ใน SQL คือการใช้ OVER คู่กับ PARTITION BY (i.e. ให้มองว่า window ก็
เหมือนการทํา grouping อย่างหนึง)
Query ด้านล่างใช้ COUNT OVER และ PARTITION BY country เพือสร้าง window อ่านเปน
ภาษาไทยง่ายๆได้ว่า “นับจํานวนลูกค้าแบ่งตามประเทศต่างๆ”
SELECT
customerid,
firstname || ' ' || lastname AS fullName,
country,
COUNT() OVER(PARTITION BY country) AS Ncountry
FROM customers;
count over คือการนับจํานวนแถว และ partition by แบ่งตามประเทศ
102
20.5 วิธก
ี ารฟลเตอร์ Result Set ทีใช้ Window Functions
เขียน subquery เพือฟลเตอร์ rowNum ระหว่าง 10-15
ู ค้ามากกว่า 10 คนขึนไป (USA)
รายชือลูกค้าทีอยูใ่ นประเทศทีมีลก
103
20.6 ตัวอย่างการแบ่งกลุ่มลูกค้าตามจํานวน segment ทีกําหนด
SELECT
*, NTILE(4) OVER(ORDER BY mb) AS segment
FROM (
SELECT
name,
ROUND(bytes/(1024.0*1024.0),2) AS mb
FROM tracks
);
คอลัมน์ segment จะมีค่าอยูร่ ะหว่าง 1-4 โดย 1 คือกลุ่มทีมี mb ตาทีสุด และ 4 คือกลุ่มทีมี mb สูงทีสุด
104
20.6 รีวิว Syntax การเขียน Window Functions
SELECT * FROM (
SELECT
*,
RANK() OVER(PARTITION BY country ORDER BY totalSpend DESC) AS rank
FROM (
SELECT
A.customerid,
A.firstname || ' ' || A.lastname AS fullName,
A.country,
SUM(total) AS totalSpend
FROM customers A
JOIN invoices B ON A.customerid = B.customerid
GROUP BY 1, 2, 3
))
WHERE rank = 1
ORDER BY totalSpend DESC;
105
รายชือของลูกค้า top spender ของแต่ละประเทศ (ประเทศละหนึงคนเท่านัน)
Important Note
บทนีแอดคิดว่าเขียนได้ยากทีสุดเลยครับ เพราะว่า window functions จริงๆจะเชือมโยงกับการ
ตังปญหาทางธุรกิจ เหมือนตัวอย่าง query ในหัวข้อ 20.7
- Email: toy@datarockie.com
- Facebook: m.me/datarockie
แอดจะนําคอมเม้นต์ของนักเรียนทุกคนมาปรับปรุงเนือหาในหนังสือเล่มนีต่อไป และจะส่งตัว
อัพเดทให้นักเรียนเรือยๆครับ / แอดทอย
106
Congratulations
Achievement III Unlocked
ยินดีด้วย ตอนนีทุกคนเรียนจบหลักสูตรทังหมดตังแต่ basic - advanced SQL แล้ว
🤗
หนังสือเล่มนียังไม่จบ
เราจะอัพเดทหนังสือ v1.3 และส่งให้นักเรียนทุกคนอีกครังวันที 30 ธ.ค. นีครับ
107