針對 MySQL 初學者與開發人員,系統講解查詢語句的核心語法、常用函數、過濾條件、排序分頁、聚合分組、多表連接、子查詢與 CTE,附帶可直接運行的示例數據腳本。
CREATE DATABASE IF NOT EXISTS learn_mysql CHARACTER SET utf8mb4;
USE learn_mysql;
-- 視頻表
CREATE TABLE videos (
video_id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
director VARCHAR(255) NOT NULL
) ENGINE=InnoDB;
INSERT INTO videos (title, director) VALUES
('大上海', '武打片'),
('小上海', '愛情片'),
('紅上海', '喜劇片'),
('黑上海', '槍戰片'),
('大上海 2', '散打片');
-- 成績表
CREATE TABLE scores (
sname VARCHAR(25) NOT NULL,
math INT NOT NULL,
physics INT NOT NULL,
literature INT NOT NULL
) ENGINE=InnoDB;
INSERT INTO scores VALUES
('john', 68, 37, 45),
('jim', 96, 89, 92),
('bill', 65, 12, 45),
('harry', 68, 25, 82);
SELECT * FROM videos;
SELECT title, director FROM videos;
SELECT DISTINCT director FROM videos;
SELECT sname, math + physics + literature AS total_score FROM scores;
SELECT * FROM scores WHERE math > 90;
SELECT sname FROM scores WHERE math > 85;
-- AND / OR / NOT
SELECT * FROM scores WHERE math <= 25 OR physics <= 25 OR literature <= 25;
SELECT * FROM scores WHERE math > 60 AND physics > 60;
SELECT * FROM scores WHERE math BETWEEN 60 AND 80;
SELECT * FROM scores WHERE sname IN ('john', 'jim');
SELECT sname FROM scores WHERE sname LIKE '%j%'; -- 包含 j
SELECT math FROM scores WHERE math LIKE '%6%'; -- 數字隱式轉字符串匹配
SELECT * FROM videos WHERE title LIKE '大%'; -- 以 大 開頭
SELECT * FROM videos WHERE title LIKE '%海'; -- 以 海 結尾
SELECT * FROM videos WHERE director IS NULL;
SELECT * FROM videos WHERE director IS NOT NULL;
SELECT COUNT(*) AS total_students FROM scores;
SELECT AVG(math) AS avg_math FROM scores;
SELECT MIN(math) AS min_math, MAX(physics) AS max_physics FROM scores;
-- 分組聚合
SELECT sname, COUNT(*) FROM scores GROUP BY sname;
SELECT AVG(math) FROM scores GROUP BY sname; -- 無意義,示例用
-- 排序
SELECT math FROM scores ORDER BY math DESC;
SELECT math FROM scores ORDER BY math ASC; -- 默認 ASC
-- 分頁 LIMIT offset, count
SELECT math FROM scores ORDER BY math DESC LIMIT 2, 2; -- 跳過前 2 行,取 2 行(第 2 頁,每頁 2 條)
-- 組合:排序後分頁
SELECT * FROM scores ORDER BY math DESC LIMIT 0, 3; -- Top 3
-- 創建部門表
CREATE TABLE dept (
dept_id INT PRIMARY KEY,
dept_name VARCHAR(50)
);
INSERT INTO dept VALUES (1, '技術部'), (2, '市場部');
-- 員工表
CREATE TABLE emp (
emp_id INT PRIMARY KEY,
emp_name VARCHAR(50),
dept_id INT
);
INSERT INTO emp VALUES (1, 'Alice', 1), (2, 'Bob', 2), (3, 'Charlie', 1);
-- 內連接
SELECT e.emp_name, d.dept_name
FROM emp e
INNER JOIN dept d ON e.dept_id = d.dept_id;
-- 左連接(保留左表所有行)
SELECT e.emp_name, d.dept_name
FROM emp e
LEFT JOIN dept d ON e.dept_id = d.dept_id;
SELECT sname, math, (SELECT AVG(math) FROM scores) AS avg_math
FROM scores;
SELECT * FROM scores WHERE math IN (SELECT math FROM scores WHERE math > 80);
SELECT * FROM scores
WHERE (math, physics) = (SELECT math, physics FROM scores WHERE sname = 'jim');
SELECT t.sname, t.total
FROM (SELECT sname, math + physics + literature AS total FROM scores) t
WHERE t.total > 200;
SELECT * FROM dept d
WHERE EXISTS (SELECT 1 FROM emp e WHERE e.dept_id = d.dept_id);
WITH high_math AS (
SELECT sname, math FROM scores WHERE math > 80
)
SELECT h.sname, h.math, s.physics
FROM high_math h
JOIN scores s ON h.sname = s.sname;
| 分類 | 函數 | 示例 |
|---|---|---|
| 字符串 | CONCAT | CONCAT('a','b') → 'ab' |
| SUBSTRING | SUBSTRING('hello',2,3) → 'ell' | |
| LENGTH / CHAR_LENGTH | 字節長度 / 字符長度 | |
| TRIM / LTRIM / RTRIM | 去除首尾空格 | |
| 數值 | ROUND / CEIL / FLOOR | 四捨五入 / 向上 / 向下取整 |
| ABS / MOD / POW | 絕對值 / 取模 / 次方 | |
| RAND | 隨機數 0-1 | |
| FORMAT | FORMAT(12345.67, 2) → '12,345.67' | |
| 日期時間 | NOW / CURDATE / CURTIME | 當前日期時間 / 日期 / 時間 |
| DATE_FORMAT | DATE_FORMAT(NOW(), '%Y-%m-%d') | |
| DATEDIFF / TIMESTAMPDIFF | 日期差 / 時間差(指定單位) | |
| DATE_ADD / DATE_SUB | 日期加減 | |
| 流程控制 | IF / IFNULL / COALESCE | 條件判斷 / 非空默認 |
| CASE WHEN | 多條件分支 | |
| NULLIF | 相等返回 NULL |
答案提示:
1. SELECT * FROM videos WHERE title LIKE '大上海%';
2. SELECT director, COUNT(*) FROM videos GROUP BY director ORDER BY COUNT(*) DESC;
3. SELECT sname, math FROM scores WHERE math > (SELECT AVG(math) FROM scores);
4. SELECT sname, math, physics, literature FROM scores ORDER BY (math+physics+literature) DESC LIMIT 3;
5. SELECT d.dept_name, COUNT(e.emp_id) FROM dept d LEFT JOIN emp e ON d.dept_id=e.dept_id GROUP BY d.dept_id;