字符串函數
CONCAT(str1, str2, …)
將多個字符串連接成一個字符串。
SELECT CONCAT('Hello', ' ', 'World'); -- 輸出: Hello World
??SUBSTRING(str, start, length)
截取字符串的子串(起始位置從1開始)。
SELECT SUBSTRING('MySQL', 3, 2); -- 輸出: 'SQ'
??LENGTH(str)
返回字符串的字節數(注意字符集影響)。
SELECT LENGTH('數據庫'); -- UTF-8下輸出: 9(每個中文3字節)
CHAR_LENGTH(str)
返回字符串的字符數(忽略字節)。
SELECT CHAR_LENGTH('數據庫'); -- 輸出: 3
?TRIM([LEADING|TRAILING|BOTH] ‘char’ FROM str)
去除字符串兩端(或指定方向)的指定字符。
SELECT TRIM(' MySQL '); -- 輸出: 'MySQL'
數值函數
???ROUND(num, decimals)??
四舍五入到指定小數位數。
SELECT ROUND(3.1415, 2); -- 輸出: 3.14
???CEIL(num)?? 和 ??FLOOR(num)
向上取整和向下取整。
SELECT CEIL(3.2), FLOOR(3.8); -- 輸出: 4, 3
?????RAND()
生成0到1之間的隨機浮點數。
SELECT FLOOR(RAND() * 100); -- 生成0-99的隨機整數
???????ABS(num)
返回絕對值。
SELECT ABS(-10); -- 輸出: 10
日期時間函數?
?????????NOW()
返回當前日期和時間(格式:YYYY-MM-DD HH:MM:SS)。
SELECT NOW(); -- 輸出: 2023-10-01 14:30:00
???????????DATE_FORMAT(date, format)
格式化日期時間。
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日'); -- 輸出: 2023年10月01日
??DATEDIFF(date1, date2)
計算兩個日期之間的天數差。
SELECT DATEDIFF('2023-10-10', '2023-10-01'); -- 輸出: 9
TIMESTAMPDIFF(unit, start, end)
計算兩個日期的時間差(單位:DAY/MONTH/YEAR等)。
SELECT TIMESTAMPDIFF(MONTH, '2023-01-01', '2023-10-01'); -- 輸出: 9
-- 若 end_time 早于 start_time,結果為負數。
支持的 unit 參數值:
單位 | 說明 | 示例 |
---|---|---|
MICROSECOND | 微秒差(1秒=1,000,000微秒) | TIMESTAMPDIFF(MICROSECOND, ‘08:00:00’, ‘08:00:00.123456’) → 123456 |
SECOND | 整數秒差(忽略微秒部分) | TIMESTAMPDIFF(SECOND, ‘08:00:00’, ‘08:01:30’) → 90 |
MINUTE | 整數分鐘差(基于秒差向下取整) | TIMESTAMPDIFF(MINUTE, ‘08:00:00’, ‘08:01:30’) → 1 |
HOUR | 整數小時差(基于分鐘差向下取整) | TIMESTAMPDIFF(HOUR, ‘08:15:00’, ‘12:30:00’) → 4 |
DAY | 整數天數差(基于時間差計算完整天數) | TIMESTAMPDIFF(DAY, ‘2023-10-01’, ‘2023-10-05’) → 4 |
WEEK | 整數周差(等同于 FLOOR(TIMESTAMPDIFF(DAY, …) / 7)) | TIMESTAMPDIFF(WEEK, ‘2023-10-01’, ‘2023-10-15’) → 2 |
MONTH | 整數月差(基于日歷月,忽略天數差異) | TIMESTAMPDIFF(MONTH, ‘2023-01-15’, ‘2023-03-10’) → 2 |
QUARTER | 整數季度差(1季度=3個月) | TIMESTAMPDIFF(QUARTER, ‘2023-01-01’, ‘2023-10-01’) → 3 |
YEAR | 整數年差(基于日歷年,忽略月內天數) | TIMESTAMPDIFF(YEAR, ‘2020-02-29’, ‘2023-02-28’) → 3 |
流程控制函數?
??IF(condition, value_if_true, value_if_false)
簡單條件判斷。
SELECT IF(score >= 60, '及格', '不及格') AS result FROM students;
??CASE WHEN
多條件分支處理。
SELECT CASE WHEN salary > 10000 THEN '高薪'WHEN salary > 5000 THEN '中薪'ELSE '低薪'END AS level
FROM employees;
聚合函數?
????SUM(column)
計算某列的總和。
SELECT SUM(salary) FROM employees;
??????AVG(column)
計算平均值。
SELECT AVG(score) FROM exams;
???????COUNT(column)
統計行數(注意:COUNT(*)包含NULL,COUNT(column)忽略NULL)。
SELECT COUNT(*) FROM users; -- 統計所有行數
???????GROUP_CONCAT(column SEPARATOR ‘sep’)
將分組后的多行數據合并為一個字符串。
SELECT department, GROUP_CONCAT(name SEPARATOR ', ')
FROM employees
GROUP BY department;
空值函數
???????COALESCE(value1, value2, …)??
返回第一個非NULL的值。
SELECT COALESCE(NULL, '備用值'); -- 輸出: '備用值'
?????????IFNULL(value, default)
如果值為NULL,返回默認值。
SELECT IFNULL(email, '未填寫') FROM users;
JSON操作函數
JSON 路徑語法?
$ 表示根節點。
$.key 訪問對象的鍵。
$[index] 訪問數組元素(索引從 0 開始)。
$.* 匹配所有成員。
$.a.b 嵌套訪問。
?????????JSON 創建與修改?
??JSON_ARRAY([value1, value2, …])??
創建 JSON 數組。
SELECT JSON_ARRAY('a', 1, TRUE, NULL);
-- 輸出: ["a", 1, true, null]
????JSON_OBJECT([key1, value1, key2, value2, …])
創建 JSON 對象。
SELECT JSON_OBJECT('name', 'Alice', 'age', 25);
-- 輸出: {"name": "Alice", "age": 25}
????JSON_SET(json_doc, path, val [, path, val]…)
插入或更新 JSON 中的字段(若路徑存在則更新,不存在則插入)。
SELECT JSON_SET('{"a": 1}', '$.b', 2);
-- 輸出: {"a": 1, "b": 2}
????JSON_INSERT(json_doc, path, val [, path, val]…)
僅在路徑不存在時插入新字段。
SELECT JSON_INSERT('{"a": 1}', '$.a', 100, '$.b', 2);
-- 輸出: {"a": 1, "b": 2} (僅插入不存在的路徑)
?JSON_REPLACE(json_doc, path, val [, path, val]…)
僅更新已存在的路徑。
SELECT JSON_REPLACE('{"a": 1, "b": 2}', '$.a', 100, '$.c', 3);
-- 輸出: {"a": 100, "b": 2} (僅更新存在的路徑)
??JSON_REMOVE(json_doc, path [, path]…)
刪除 JSON 中的指定路徑。
SELECT JSON_REMOVE('{"a": 1, "b": 2}', '$.a');
-- 輸出: {"b": 2}
JSON 查詢與提取?
JSON_EXTRACT(json_doc, path)?? 或 ??->?? 操作符
提取 JSON 中的值(支持路徑表達式)。
SELECT JSON_EXTRACT('{"user": {"name": "Alice", "age": 25}}', '$.user.name');
-- 輸出: "Alice"-- 等效寫法(MySQL 5.7+):
SELECT data->'$.user.age' FROM users;
JSON_UNQUOTE(json_val)
去除 JSON 字符串的引號。
SELECT JSON_UNQUOTE(JSON_EXTRACT('{"name": "Alice"}', '$.name'));
-- 輸出: Alice
JSON_CONTAINS(json_doc, val [, path])
檢查 JSON 中是否包含指定值。
SELECT JSON_CONTAINS('{"a": [1, 2, 3]}', '2', '$.a');
-- 輸出: 1 (true)
JSON_SEARCH(json_doc, ‘one|all’, search_str)
查找包含指定字符串的路徑。
SELECT JSON_SEARCH('{"user": {"name": "Alice"}}', 'one', 'Alice');
-- 輸出: "$.user.name"
JSON 聚合與轉換?
??JSON_ARRAYAGG(expr)
將多行數據聚合為 JSON 數組。
SELECT JSON_ARRAYAGG(name) FROM users;
-- 輸出: ["Alice", "Bob", "Charlie"]
????JSON_OBJECTAGG(key, value)
將鍵值對聚合為 JSON 對象。
SELECT JSON_OBJECTAGG(id, name) FROM users;
-- 輸出: {"1": "Alice", "2": "Bob"}
JSON_TYPE(json_val)??
返回 JSON 值的類型(如 OBJECT, ARRAY, STRING, INTEGER)。
SELECT JSON_TYPE(JSON_EXTRACT('{"a": [1, "b"]}', '$.a'));
-- 輸出: ARRAY
子查詢
子查詢類型
標量子查詢(Scalar Subquery)??
返回單個值(一行一列)。
常用在 ??SELECT??、??WHERE?? 或 ??HAVING?? 中。
-- 示例:查詢工資高于平均工資的員工
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
行子查詢(Row Subquery)??
返回單行多列。
-- 示例:查詢工資高于平均工資的員工
-- 示例:查詢與指定員工部門和職位相同的其他員工
SELECT name
FROM employees
WHERE (department, job_title) = (SELECT department, job_title FROM employees WHERE name = 'Alice'
);
列子查詢(Column Subquery)??
返回多行單列。
常與 ??IN??、??ANY??、??ALL?? 等操作符搭配使用。
-- 示例:查詢所有在銷售部或技術部的員工
SELECT name
FROM employees
WHERE department IN (SELECT department FROM departments WHERE location = 'New York'
);
表子查詢(Table Subquery)??
返回多行多列。
通常作為派生表(Derived Table)出現在 ??FROM?? 子句。
-- 示例:查詢每個部門的平均工資,并與公司平均工資比較
SELECT department, AVG(salary) AS dept_avg,(SELECT AVG(salary) FROM employees) AS company_avg
FROM employees
GROUP BY department;
子查詢與操作符?
IN / NOT IN?
-- 示例:查詢購買了某產品的客戶
SELECT customer_name
FROM customers
WHERE customer_id IN (SELECT customer_id FROM orders WHERE product_id = 1001
);
ANY / SOME?
與比較符(>、<、= 等)搭配,表示滿足任一結果。
-- 示例:查詢工資高于技術部任一員工的員工
SELECT name
FROM employees
WHERE salary > ANY (SELECT salary FROM employees WHERE department = '技術部'
);
?ALL?
表示滿足所有結果。
-- 示例:查詢工資高于所有技術部員工的員工
SELECT name
FROM employees
WHERE salary > ALL (SELECT salary FROM employees WHERE department = '技術部'
);
??EXISTS / NOT EXISTS?
檢查子查詢是否返回結果(更高效,常用于關聯子查詢)。
-- 示例:查詢至少有一個訂單的客戶
SELECT customer_name
FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id
);
類型轉換函數
CAST(expr AS type)?
?功能??:將表達式轉換為指定類型。
??支持類型??:
BINARY(二進制)
CHAR(字符串)
DATE、DATETIME、TIME
DECIMAL
SIGNED(有符號整數)、UNSIGNED(無符號整數)
-- 字符串轉整數
SELECT CAST('123' AS SIGNED); -- 輸出: 123-- 浮點數轉 DECIMAL(控制精度)
SELECT CAST(3.1415 AS DECIMAL(5,2)); -- 輸出: 3.14 (總位數 5,小數位 2)-- 時間戳轉日期
SELECT CAST(NOW() AS DATE); -- 輸出: 2023-10-01
CONVERT(expr, type)?? 或 ??CONVERT(expr USING charset)
功能??:
轉換數據類型(同 CAST)。
轉換字符集(如 utf8mb4 轉 latin1)。
-- 字符串轉整數
SELECT CONVERT('456', SIGNED); -- 輸出: 456-- 轉換字符集
SELECT CONVERT('你好' USING latin1); -- 輸出可能為亂碼(如字符集不支持)
with as 子句
WITH dept_avg AS (SELECT department, AVG(salary) AS avg_salary FROM employees GROUP BY department
)
SELECT * FROM dept_avg WHERE avg_salary > 10000;
union
SELECT column1, column2 FROM table1
UNION [ALL | DISTINCT]
SELECT column1, column2 FROM table2
[ORDER BY column1]
[LIMIT N];
?UNION DISTINCT??:默認行為,合并結果并去重。
??UNION ALL??:保留所有重復行。
??ORDER BY?? 和 ??LIMIT??:對整個合并后的結果集生效(非單個查詢)。
group by having
對分組后的結果進行過濾(類似于 WHERE,但作用于分組后的數據)。
SELECT column1, aggregate_function(column2)
FROM table
GROUP BY column1
HAVING condition;
GROUP BY 與 WHERE 的區別??:
??WHERE??:在分組前過濾數據(作用于原始數據行)。
??HAVING??:在分組后過濾數據(作用于聚合結果)。
SELECT employee_id, COUNT(*) AS order_count
FROM orders
WHERE department = '銷售部' -- 先過濾部門
GROUP BY employee_id
HAVING order_count > 50; -- 再過濾分組結果