จัดโครงสร้างคิวรีของคุณเป็นขั้นตอนที่มีชื่อด้วย WITH และเชื่อมต่อ CTE หลายตัวเข้าด้วยกันเหมือนไปป์ไลน์ของการแปลงข้อมูล
เปิดบทเรียนนี้ใน Kodokonคิวรีย่อยที่ซ้อนกันลึกสามชั้นต้องอ่านจากในออกนอก ทั้งอ่านยากและกลับมาแก้ไขไม่ได้เลยในอีกหกเดือนต่อมา CTE (Common Table Expression หรือคำสั่ง WITH) จะพลิกลำดับการอ่าน คุณตั้งชื่อให้แต่ละขั้นตอนกลาง เหมือนกับที่คุณตั้งชื่อฟังก์ชัน และคิวรีจะอ่านจากบนลงล่าง จงโหลดชุดข้อมูลนี้เข้าไปใน sqliteonline.com หรือ sqlite3
CREATE TABLE payments (
id INTEGER PRIMARY KEY,
customer TEXT NOT NULL,
paid_at TEXT NOT NULL,
amount REAL NOT NULL
);
INSERT INTO payments (customer, paid_at, amount)
VALUES
('alice', '2026-01-10', 120.0),
('bruno', '2026-01-22', 80.0),
('alice', '2026-02-05', 60.0),
('chloe', '2026-02-18', 200.0),
('bruno', '2026-03-03', 40.0),
('alice', '2026-03-15', 90.0),
('chloe', '2026-03-28', 150.0),
('bruno', '2026-04-09', 300.0);ไวยากรณ์พื้นฐาน: WITH name AS (SELECT ...) ตามด้วยคิวรีหลักที่ใช้ name เหมือนตารางธรรมดา ในที่นี้ เราคำนวณรายได้รายเดือนโดยดึงเดือนออกจากวันที่ด้วย substr (วันที่ใน SQLite เป็นข้อความรูปแบบ ISO 8601 ซึ่งเป็นทางเลือกของเอนจินมากกว่าจะเป็นมาตรฐาน)
WITH monthly AS (
SELECT substr(paid_at, 1, 7) AS month,
SUM(amount) AS revenue
FROM payments
GROUP BY month
)
SELECT * FROM monthly ORDER BY month;พลังที่แท้จริงมาจากการ เชื่อมต่อกัน (chaining) คือมี WITH เพียงตัวเดียว มี CTE หลายตัวคั่นด้วยจุลภาค โดยแต่ละตัวสามารถอ่าน CTE ที่ประกาศไว้ก่อนหน้าได้ คุณสร้างไปป์ไลน์ขึ้นมา ได้แก่ รวมกลุ่ม, คำนวณค่าสถิติ, เปรียบเทียบ ในที่นี้ เรามองหาเดือนที่มีรายได้เกินค่าเฉลี่ยรายเดือน (คาดว่า: 2026-03 และ 2026-04 โดยค่าเฉลี่ยคือ 260)
WITH monthly AS (
SELECT substr(paid_at, 1, 7) AS month,
SUM(amount) AS revenue
FROM payments
GROUP BY month
),
stats AS (
SELECT AVG(revenue) AS avg_revenue
FROM monthly
)
SELECT m.month, m.revenue,
ROUND(s.avg_revenue, 1) AS avg_all
FROM monthly AS m
CROSS JOIN stats AS s
WHERE m.revenue > s.avg_revenue
ORDER BY m.month;