🔧 MySQL 函数

内置函数详解与实用示例 - 字符串、数值、日期时间、聚合函数

函数概述

MySQL 提供了丰富的内置函数,用于处理字符串、数值、日期时间等数据类型。合理使用函数可以简化查询逻辑,提高开发效率。

📝 字符串函数

处理文本数据,包括连接、截取、替换、格式化等操作

🔢 数值函数

数学运算、取整、随机数、三角函数等数值处理

📅 日期时间函数

日期时间的格式化、计算、提取和转换操作

📊 聚合函数

统计计算,如求和、平均值、计数、最值等

🔄 控制流函数

条件判断、空值处理、流程控制等逻辑操作

🔍 信息函数

获取系统信息、连接信息、版本信息等

准备测试环境

-- 创建测试数据库 CREATE DATABASE function_demo; USE function_demo; -- 创建员工表 CREATE TABLE employees ( id INT AUTO_INCREMENT PRIMARY KEY, first_name VARCHAR(50), last_name VARCHAR(50), email VARCHAR(100), phone VARCHAR(20), hire_date DATE, salary DECIMAL(10,2), department VARCHAR(50), birth_date DATE, is_active BOOLEAN DEFAULT TRUE ); -- 插入测试数据 INSERT INTO employees (first_name, last_name, email, phone, hire_date, salary, department, birth_date) VALUES ('张', '三', 'zhang.san@company.com', '13800138001', '2020-01-15', 8500.00, '技术部', '1990-05-20'), ('李', '四', 'li.si@company.com', '13800138002', '2019-03-22', 9200.00, '销售部', '1988-08-15'), ('王', '五', 'wang.wu@company.com', '13800138003', '2021-06-10', 7800.00, '技术部', '1992-12-03'), ('赵', '六', 'zhao.liu@company.com', '13800138004', '2018-09-05', 10500.00, '管理部', '1985-03-28'), ('钱', '七', 'qian.qi@company.com', '13800138005', '2022-02-14', 6500.00, '人事部', '1995-07-12'), ('孙', '八', 'sun.ba@company.com', '13800138006', '2020-11-30', 8800.00, '财务部', '1987-11-25'), ('周', '九', 'zhou.jiu@company.com', '13800138007', '2019-07-18', 9500.00, '技术部', '1991-04-08'), ('吴', '十', 'wu.shi@company.com', '13800138008', '2021-12-01', 7200.00, '销售部', '1993-09-17'); -- 创建产品表 CREATE TABLE products ( id INT AUTO_INCREMENT PRIMARY KEY, product_name VARCHAR(100), price DECIMAL(10,2), stock_quantity INT, category VARCHAR(50), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, description TEXT ); -- 插入产品数据 INSERT INTO products (product_name, price, stock_quantity, category, description) VALUES ('iPhone 15 Pro', 7999.00, 50, '手机', '苹果最新旗舰手机'), ('MacBook Pro 16"', 19999.00, 20, '电脑', '专业级笔记本电脑'), ('iPad Air', 4599.00, 30, '平板', '轻薄便携平板电脑'), ('AirPods Pro', 1899.00, 100, '耳机', '主动降噪无线耳机'), ('Apple Watch Series 9', 2999.00, 80, '手表', '智能运动手表'); SELECT 'Test data created successfully' AS message;

字符串函数

基本字符串操作

-- 1. 字符串连接 -- CONCAT() - 连接多个字符串 SELECT first_name, last_name, CONCAT(first_name, ' ', last_name) AS full_name, CONCAT(first_name, '(', department, ')') AS name_with_dept FROM employees; -- CONCAT_WS() - 使用分隔符连接 SELECT CONCAT_WS(' - ', first_name, last_name, department) AS employee_info, CONCAT_WS('@', LOWER(first_name), 'company.com') AS generated_email FROM employees; -- 2. 字符串长度和截取 -- LENGTH() - 字节长度, CHAR_LENGTH() - 字符长度 SELECT product_name, LENGTH(product_name) AS byte_length, CHAR_LENGTH(product_name) AS char_length, LEFT(product_name, 10) AS left_10, RIGHT(product_name, 5) AS right_5, SUBSTRING(product_name, 1, 8) AS substr_8 FROM products; -- 3. 字符串查找和替换 -- LOCATE(), POSITION(), INSTR() - 查找子字符串位置 SELECT email, LOCATE('@', email) AS at_position, SUBSTRING(email, 1, LOCATE('@', email) - 1) AS username, SUBSTRING(email, LOCATE('@', email) + 1) AS domain, REPLACE(email, '@company.com', '@newcompany.com') AS new_email FROM employees; -- 4. 大小写转换 SELECT product_name, UPPER(product_name) AS uppercase, LOWER(product_name) AS lowercase, INITCAP(product_name) AS title_case -- MySQL 8.0+ FROM products; -- 5. 字符串修剪和填充 SELECT ' hello world ' AS original, TRIM(' hello world ') AS trimmed, LTRIM(' hello world ') AS left_trimmed, RTRIM(' hello world ') AS right_trimmed, LPAD('123', 8, '0') AS left_padded, RPAD('abc', 10, '*') AS right_padded;

高级字符串处理

-- 1. 字符串反转和重复 SELECT first_name, REVERSE(first_name) AS reversed_name, REPEAT(first_name, 3) AS repeated_name, REPEAT('*', CHAR_LENGTH(first_name)) AS masked_name FROM employees; -- 2. 字符串比较 SELECT first_name, last_name, STRCMP(first_name, last_name) AS name_comparison, CASE WHEN STRCMP(first_name, last_name) = 0 THEN '相同' WHEN STRCMP(first_name, last_name) < 0 THEN '姓小于名' ELSE '姓大于名' END AS comparison_result FROM employees; -- 3. 字符串格式化 SELECT first_name, salary, FORMAT(salary, 2) AS formatted_salary, CONCAT('¥', FORMAT(salary, 2)) AS currency_format, INSERT(phone, 4, 4, '****') AS masked_phone -- 手机号脱敏 FROM employees; -- 4. 字符串编码和解码 SELECT product_name, HEX(product_name) AS hex_encoded, UNHEX(HEX(product_name)) AS hex_decoded, TO_BASE64(product_name) AS base64_encoded, FROM_BASE64(TO_BASE64(product_name)) AS base64_decoded FROM products LIMIT 3; -- 5. 正则表达式匹配 SELECT email, email REGEXP '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' AS is_valid_email, REGEXP_REPLACE(phone, '(\d{3})(\d{4})(\d{4})', '$1-$2-$3') AS formatted_phone FROM employees;

常用字符串函数总结

函数 语法 说明 示例
CONCAT CONCAT(str1, str2, ...) 连接字符串 CONCAT('Hello', ' ', 'World')
SUBSTRING SUBSTRING(str, pos, len) 截取子字符串 SUBSTRING('Hello', 2, 3) → 'ell'
LENGTH LENGTH(str) 字符串字节长度 LENGTH('Hello') → 5
UPPER/LOWER UPPER(str), LOWER(str) 大小写转换 UPPER('hello') → 'HELLO'
TRIM TRIM(str) 去除首尾空格 TRIM(' hello ') → 'hello'
REPLACE REPLACE(str, from, to) 字符串替换 REPLACE('hello', 'l', 'x') → 'hexxo'

数值函数

基本数学运算

-- 1. 基本数学函数 SELECT salary, ABS(salary - 8000) AS salary_diff, ROUND(salary / 12, 2) AS monthly_salary, CEIL(salary / 1000) AS salary_k_ceil, FLOOR(salary / 1000) AS salary_k_floor, TRUNCATE(salary / 12, 1) AS monthly_truncated FROM employees; -- 2. 幂运算和开方 SELECT stock_quantity, POWER(stock_quantity, 2) AS quantity_squared, SQRT(stock_quantity) AS quantity_sqrt, EXP(1) AS euler_number, LOG(stock_quantity) AS natural_log, LOG10(stock_quantity) AS log_base_10 FROM products WHERE stock_quantity > 0; -- 3. 三角函数 SELECT PI() AS pi_value, SIN(PI()/2) AS sin_90_degrees, COS(0) AS cos_0_degrees, TAN(PI()/4) AS tan_45_degrees, DEGREES(PI()) AS pi_in_degrees, RADIANS(180) AS degrees_180_in_radians; -- 4. 随机数和符号函数 SELECT RAND() AS random_0_to_1, RAND(123) AS seeded_random, FLOOR(RAND() * 100) + 1 AS random_1_to_100, SIGN(-15) AS negative_sign, SIGN(0) AS zero_sign, SIGN(25) AS positive_sign; -- 5. 取模和最值 SELECT id, salary, MOD(salary, 1000) AS salary_mod_1000, GREATEST(salary, 8000, 9000) AS max_value, LEAST(salary, 8000, 9000) AS min_value FROM employees;

数值格式化和转换

-- 1. 数值格式化 SELECT salary, FORMAT(salary, 0) AS formatted_no_decimal, FORMAT(salary, 2) AS formatted_2_decimal, CONV(id, 10, 2) AS id_binary, CONV(id, 10, 16) AS id_hex, BIN(id) AS id_binary_func, HEX(id) AS id_hex_func FROM employees; -- 2. 数值统计函数在查询中的应用 SELECT department, COUNT(*) AS employee_count, AVG(salary) AS avg_salary, ROUND(AVG(salary), 2) AS avg_salary_rounded, STDDEV(salary) AS salary_stddev, VARIANCE(salary) AS salary_variance FROM employees GROUP BY department; -- 3. 累积计算 SELECT id, first_name, salary, @running_total := @running_total + salary AS running_total, @row_number := @row_number + 1 AS row_num FROM employees, (SELECT @running_total := 0, @row_number := 0) AS vars ORDER BY salary DESC;

常用数值函数总结

函数 语法 说明 示例
ROUND ROUND(num, decimals) 四舍五入 ROUND(3.14159, 2) → 3.14
CEIL/CEILING CEIL(num) 向上取整 CEIL(3.1) → 4
FLOOR FLOOR(num) 向下取整 FLOOR(3.9) → 3
ABS ABS(num) 绝对值 ABS(-5) → 5
MOD MOD(num, divisor) 取模运算 MOD(10, 3) → 1
POWER POWER(base, exponent) 幂运算 POWER(2, 3) → 8

日期时间函数

获取当前日期时间

-- 1. 当前日期时间函数 SELECT NOW() AS current_datetime, CURDATE() AS current_date, CURTIME() AS current_time, CURRENT_TIMESTAMP AS current_timestamp, UTC_TIMESTAMP() AS utc_timestamp, UNIX_TIMESTAMP() AS unix_timestamp, FROM_UNIXTIME(UNIX_TIMESTAMP()) AS from_unix; -- 2. 日期时间提取 SELECT hire_date, YEAR(hire_date) AS hire_year, MONTH(hire_date) AS hire_month, DAY(hire_date) AS hire_day, DAYNAME(hire_date) AS hire_day_name, MONTHNAME(hire_date) AS hire_month_name, QUARTER(hire_date) AS hire_quarter, WEEK(hire_date) AS hire_week, DAYOFYEAR(hire_date) AS hire_day_of_year, WEEKDAY(hire_date) AS hire_weekday FROM employees; -- 3. 日期时间格式化 SELECT hire_date, DATE_FORMAT(hire_date, '%Y-%m-%d') AS formatted_date, DATE_FORMAT(hire_date, '%Y年%m月%d日') AS chinese_date, DATE_FORMAT(hire_date, '%W, %M %d, %Y') AS english_date, TIME_FORMAT(NOW(), '%H:%i:%s') AS formatted_time, DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s') AS full_datetime FROM employees;

日期时间计算

-- 1. 日期加减运算 SELECT hire_date, DATE_ADD(hire_date, INTERVAL 1 YEAR) AS one_year_later, DATE_SUB(hire_date, INTERVAL 6 MONTH) AS six_months_before, ADDDATE(hire_date, 30) AS thirty_days_later, SUBDATE(hire_date, 15) AS fifteen_days_before, hire_date + INTERVAL 1 WEEK AS one_week_later FROM employees; -- 2. 日期差值计算 SELECT first_name, hire_date, birth_date, DATEDIFF(CURDATE(), hire_date) AS days_since_hire, DATEDIFF(CURDATE(), birth_date) AS days_since_birth, TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) AS age_years, TIMESTAMPDIFF(MONTH, hire_date, CURDATE()) AS months_employed, TIMESTAMPDIFF(DAY, hire_date, CURDATE()) AS days_employed FROM employees; -- 3. 工作日和周末计算 SELECT hire_date, DAYOFWEEK(hire_date) AS day_of_week_num, CASE DAYOFWEEK(hire_date) WHEN 1 THEN '周日' WHEN 2 THEN '周一' WHEN 3 THEN '周二' WHEN 4 THEN '周三' WHEN 5 THEN '周四' WHEN 6 THEN '周五' WHEN 7 THEN '周六' END AS day_of_week_chinese, CASE WHEN DAYOFWEEK(hire_date) IN (1, 7) THEN '周末' ELSE '工作日' END AS day_type FROM employees; -- 4. 月份和季度处理 SELECT hire_date, LAST_DAY(hire_date) AS last_day_of_month, DATE_FORMAT(hire_date, '%Y-%m-01') AS first_day_of_month, MAKEDATE(YEAR(hire_date), 1) AS first_day_of_year, STR_TO_DATE(CONCAT(YEAR(hire_date), '-12-31'), '%Y-%m-%d') AS last_day_of_year, CASE QUARTER(hire_date) WHEN 1 THEN CONCAT(YEAR(hire_date), '-01-01') WHEN 2 THEN CONCAT(YEAR(hire_date), '-04-01') WHEN 3 THEN CONCAT(YEAR(hire_date), '-07-01') WHEN 4 THEN CONCAT(YEAR(hire_date), '-10-01') END AS quarter_start FROM employees;

日期时间转换

-- 1. 字符串与日期转换 SELECT '2024-01-15' AS date_string, STR_TO_DATE('2024-01-15', '%Y-%m-%d') AS parsed_date, STR_TO_DATE('15/01/2024', '%d/%m/%Y') AS parsed_date_dmy, STR_TO_DATE('2024-01-15 14:30:00', '%Y-%m-%d %H:%i:%s') AS parsed_datetime, DATE('2024-01-15 14:30:00') AS extract_date, TIME('2024-01-15 14:30:00') AS extract_time; -- 2. Unix 时间戳转换 SELECT UNIX_TIMESTAMP('2024-01-15 12:00:00') AS to_unix_timestamp, FROM_UNIXTIME(1705294800) AS from_unix_timestamp, FROM_UNIXTIME(1705294800, '%Y-%m-%d %H:%i:%s') AS formatted_from_unix; -- 3. 时区转换 SELECT NOW() AS local_time, UTC_TIMESTAMP() AS utc_time, CONVERT_TZ(NOW(), @@session.time_zone, '+00:00') AS converted_to_utc, CONVERT_TZ(NOW(), '+08:00', '+00:00') AS beijing_to_utc; -- 4. 实际应用示例 -- 计算员工年龄和工作年限 SELECT CONCAT(first_name, ' ', last_name) AS full_name, birth_date, hire_date, TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) AS age, TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) AS years_of_service, CASE WHEN TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) >= 5 THEN '资深员工' WHEN TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) >= 2 THEN '经验员工' ELSE '新员工' END AS employee_level, DATE_ADD(hire_date, INTERVAL 5 YEAR) AS five_year_anniversary FROM employees ORDER BY years_of_service DESC;

常用日期时间函数总结

函数 语法 说明 示例
NOW NOW() 当前日期时间 2024-01-15 14:30:00
DATE_FORMAT DATE_FORMAT(date, format) 日期格式化 DATE_FORMAT(NOW(), '%Y-%m-%d')
DATE_ADD DATE_ADD(date, INTERVAL expr unit) 日期加法 DATE_ADD(NOW(), INTERVAL 1 DAY)
DATEDIFF DATEDIFF(date1, date2) 日期差值(天数) DATEDIFF('2024-01-15', '2024-01-01')
YEAR/MONTH/DAY YEAR(date), MONTH(date), DAY(date) 提取年月日 YEAR('2024-01-15') → 2024
STR_TO_DATE STR_TO_DATE(str, format) 字符串转日期 STR_TO_DATE('2024-01-15', '%Y-%m-%d')

聚合函数

基本聚合函数

-- 1. 基本统计函数 SELECT COUNT(*) AS total_employees, COUNT(DISTINCT department) AS unique_departments, SUM(salary) AS total_salary, AVG(salary) AS average_salary, MIN(salary) AS minimum_salary, MAX(salary) AS maximum_salary, MIN(hire_date) AS earliest_hire, MAX(hire_date) AS latest_hire FROM employees; -- 2. 按部门分组统计 SELECT department, COUNT(*) AS employee_count, ROUND(AVG(salary), 2) AS avg_salary, MIN(salary) AS min_salary, MAX(salary) AS max_salary, SUM(salary) AS total_salary, STDDEV(salary) AS salary_stddev, VARIANCE(salary) AS salary_variance FROM employees GROUP BY department ORDER BY avg_salary DESC; -- 3. 条件聚合 SELECT department, COUNT(*) AS total_count, COUNT(CASE WHEN salary > 8000 THEN 1 END) AS high_salary_count, COUNT(CASE WHEN TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) >= 3 THEN 1 END) AS senior_count, ROUND(AVG(CASE WHEN salary > 8000 THEN salary END), 2) AS avg_high_salary, SUM(CASE WHEN salary > 8000 THEN salary ELSE 0 END) AS total_high_salary FROM employees GROUP BY department; -- 4. 产品统计 SELECT category, COUNT(*) AS product_count, ROUND(AVG(price), 2) AS avg_price, MIN(price) AS min_price, MAX(price) AS max_price, SUM(stock_quantity) AS total_stock, ROUND(AVG(stock_quantity), 0) AS avg_stock FROM products GROUP BY category ORDER BY avg_price DESC;

高级聚合和窗口函数

-- 1. 窗口函数(MySQL 8.0+) SELECT first_name, last_name, department, salary, ROW_NUMBER() OVER (ORDER BY salary DESC) AS salary_rank, RANK() OVER (ORDER BY salary DESC) AS salary_rank_with_ties, DENSE_RANK() OVER (ORDER BY salary DESC) AS salary_dense_rank, PERCENT_RANK() OVER (ORDER BY salary) AS salary_percentile, NTILE(4) OVER (ORDER BY salary) AS salary_quartile FROM employees; -- 2. 部门内排名 SELECT first_name, last_name, department, salary, ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank, LAG(salary) OVER (PARTITION BY department ORDER BY salary DESC) AS prev_salary, LEAD(salary) OVER (PARTITION BY department ORDER BY salary DESC) AS next_salary, salary - LAG(salary) OVER (PARTITION BY department ORDER BY salary DESC) AS salary_diff FROM employees; -- 3. 累积计算 SELECT first_name, department, salary, SUM(salary) OVER (ORDER BY hire_date) AS running_total, AVG(salary) OVER (ORDER BY hire_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_3, COUNT(*) OVER (PARTITION BY department) AS dept_total_count, SUM(salary) OVER (PARTITION BY department) AS dept_total_salary FROM employees ORDER BY hire_date; -- 4. 分组集合函数(MySQL 8.0+) SELECT department, YEAR(hire_date) AS hire_year, COUNT(*) AS employee_count, ROUND(AVG(salary), 2) AS avg_salary FROM employees GROUP BY department, YEAR(hire_date) WITH ROLLUP;

自定义聚合函数

-- 1. 使用 GROUP_CONCAT 创建聚合字符串 SELECT department, COUNT(*) AS employee_count, GROUP_CONCAT(CONCAT(first_name, ' ', last_name) ORDER BY salary DESC SEPARATOR ', ') AS employees, GROUP_CONCAT(DISTINCT YEAR(hire_date) ORDER BY YEAR(hire_date) SEPARATOR ', ') AS hire_years, GROUP_CONCAT(salary ORDER BY salary DESC SEPARATOR ' | ') AS salaries FROM employees GROUP BY department; -- 2. 计算中位数(模拟) SELECT department, COUNT(*) AS total_count, ROUND(AVG(salary), 2) AS mean_salary, ( SELECT ROUND(AVG(salary), 2) FROM ( SELECT salary FROM employees e2 WHERE e2.department = e1.department ORDER BY salary LIMIT 2 - (SELECT COUNT(*) FROM employees e3 WHERE e3.department = e1.department) % 2 OFFSET (SELECT (COUNT(*) - 1) DIV 2 FROM employees e3 WHERE e3.department = e1.department) ) AS median_calc ) AS median_salary FROM employees e1 GROUP BY department; -- 3. 自定义统计指标 SELECT department, COUNT(*) AS employee_count, ROUND(AVG(salary), 2) AS avg_salary, ROUND(STDDEV(salary), 2) AS salary_stddev, ROUND((MAX(salary) - MIN(salary)), 2) AS salary_range, ROUND(AVG(TIMESTAMPDIFF(YEAR, birth_date, CURDATE())), 1) AS avg_age, ROUND(AVG(TIMESTAMPDIFF(YEAR, hire_date, CURDATE())), 1) AS avg_tenure, COUNT(CASE WHEN salary > (SELECT AVG(salary) FROM employees) THEN 1 END) AS above_avg_count FROM employees GROUP BY department ORDER BY avg_salary DESC;

常用聚合函数总结

函数 语法 说明 示例
COUNT COUNT(*), COUNT(column) 计数 COUNT(*) → 总行数
SUM SUM(column) 求和 SUM(salary) → 工资总和
AVG AVG(column) 平均值 AVG(salary) → 平均工资
MIN/MAX MIN(column), MAX(column) 最小值/最大值 MIN(salary), MAX(salary)
GROUP_CONCAT GROUP_CONCAT(column SEPARATOR sep) 字符串聚合 GROUP_CONCAT(name SEPARATOR ', ')
STDDEV STDDEV(column) 标准差 STDDEV(salary) → 工资标准差

控制流函数

条件判断函数

-- 1. IF 函数 SELECT first_name, salary, IF(salary > 8000, '高薪', '普通') AS salary_level, IF(TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) >= 3, '资深', '新人') AS experience_level, IF(department = '技术部', salary * 1.1, salary) AS adjusted_salary FROM employees; -- 2. CASE 语句 SELECT first_name, last_name, salary, department, CASE WHEN salary >= 10000 THEN 'A级' WHEN salary >= 8000 THEN 'B级' WHEN salary >= 6000 THEN 'C级' ELSE 'D级' END AS salary_grade, CASE department WHEN '技术部' THEN '核心部门' WHEN '销售部' THEN '业务部门' WHEN '管理部' THEN '管理部门' ELSE '支持部门' END AS department_type FROM employees; -- 3. NULLIF 和 IFNULL SELECT product_name, price, stock_quantity, IFNULL(description, '暂无描述') AS product_description, NULLIF(stock_quantity, 0) AS non_zero_stock, COALESCE(description, product_name, '未知产品') AS display_name FROM products; -- 4. 复杂条件判断 SELECT first_name, birth_date, hire_date, salary, CASE WHEN TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) < 30 THEN '年轻员工' WHEN TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) BETWEEN 30 AND 40 THEN '中年员工' ELSE '资深员工' END AS age_group, CASE WHEN salary > (SELECT AVG(salary) FROM employees) AND TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) >= 2 THEN '优秀员工' WHEN salary > (SELECT AVG(salary) FROM employees) THEN '高薪新人' WHEN TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) >= 3 THEN '忠诚员工' ELSE '普通员工' END AS employee_category FROM employees;

空值处理函数

-- 1. 空值检测和处理 SELECT product_name, description, ISNULL(description) AS is_desc_null, description IS NULL AS is_null_check, description IS NOT NULL AS is_not_null_check, IFNULL(description, '暂无描述') AS desc_with_default, COALESCE(description, product_name, '未知') AS coalesced_value FROM products; -- 2. 空值替换和转换 SELECT first_name, email, phone, CASE WHEN email IS NULL THEN '邮箱未填写' WHEN email = '' THEN '邮箱为空' ELSE email END AS email_status, NULLIF(phone, '') AS clean_phone, -- 将空字符串转为 NULL IF(phone IS NULL OR phone = '', '未提供', phone) AS phone_display FROM employees; -- 3. 条件聚合中的空值处理 SELECT department, COUNT(*) AS total_employees, COUNT(email) AS employees_with_email, COUNT(*) - COUNT(email) AS employees_without_email, ROUND(COUNT(email) * 100.0 / COUNT(*), 2) AS email_completion_rate FROM employees GROUP BY department;

常用控制流函数总结

函数 语法 说明 示例
IF IF(condition, true_value, false_value) 条件判断 IF(salary > 8000, '高薪', '普通')
CASE CASE WHEN condition THEN value END 多条件判断 CASE WHEN salary > 8000 THEN '高薪' ELSE '普通' END
IFNULL IFNULL(expr, default_value) 空值替换 IFNULL(description, '暂无描述')
COALESCE COALESCE(expr1, expr2, ...) 返回第一个非空值 COALESCE(desc, name, '未知')
NULLIF NULLIF(expr1, expr2) 相等时返回NULL NULLIF(quantity, 0)
ISNULL ISNULL(expr) 检查是否为空 ISNULL(description)

信息函数

-- 1. 系统信息函数 SELECT VERSION() AS mysql_version, USER() AS current_user, CURRENT_USER() AS current_user_host, DATABASE() AS current_database, CONNECTION_ID() AS connection_id, CHARSET('hello') AS default_charset, COLLATION('hello') AS default_collation; -- 2. 会话和连接信息 SELECT @@version AS version_variable, @@hostname AS hostname, @@port AS port, @@datadir AS data_directory, @@character_set_server AS server_charset, @@collation_server AS server_collation, @@time_zone AS time_zone; -- 3. 最后插入ID和影响行数 -- 这些函数通常在INSERT/UPDATE/DELETE后使用 SELECT LAST_INSERT_ID() AS last_insert_id, ROW_COUNT() AS affected_rows, FOUND_ROWS() AS found_rows; -- 需要在SELECT中使用SQL_CALC_FOUND_ROWS -- 4. 表和列信息 SELECT TABLE_NAME, TABLE_ROWS, DATA_LENGTH, INDEX_LENGTH, CREATE_TIME, UPDATE_TIME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'function_demo'; -- 5. 性能和状态信息 SELECT BENCHMARK(1000000, 1+1) AS benchmark_result; -- 性能测试 SHOW STATUS LIKE 'Connections'; SHOW STATUS LIKE 'Uptime'; SHOW STATUS LIKE 'Questions';

常用信息函数总结

函数 说明 返回值示例
VERSION() MySQL版本 8.0.35
USER() 当前用户 root@localhost
DATABASE() 当前数据库 function_demo
CONNECTION_ID() 连接ID 123
LAST_INSERT_ID() 最后插入的自增ID 15
ROW_COUNT() 影响的行数 3

实际应用示例

数据清洗和格式化

-- 1. 员工数据清洗 SELECT id, TRIM(CONCAT(first_name, ' ', last_name)) AS full_name, LOWER(TRIM(email)) AS clean_email, REGEXP_REPLACE(phone, '[^0-9]', '') AS clean_phone, UPPER(TRIM(department)) AS clean_department, CASE WHEN salary < 0 THEN 0 WHEN salary > 50000 THEN 50000 ELSE salary END AS validated_salary FROM employees; -- 2. 产品数据标准化 SELECT id, TRIM(product_name) AS clean_name, ROUND(price, 2) AS formatted_price, GREATEST(0, stock_quantity) AS positive_stock, UPPER(TRIM(category)) AS standard_category, COALESCE(NULLIF(TRIM(description), ''), '暂无描述') AS clean_description, CONCAT('¥', FORMAT(price, 2)) AS display_price FROM products;

报表和统计分析

-- 1. 员工统计报表 SELECT '总体统计' AS category, COUNT(*) AS employee_count, CONCAT('¥', FORMAT(AVG(salary), 2)) AS avg_salary, CONCAT('¥', FORMAT(MIN(salary), 2)) AS min_salary, CONCAT('¥', FORMAT(MAX(salary), 2)) AS max_salary, ROUND(AVG(TIMESTAMPDIFF(YEAR, birth_date, CURDATE())), 1) AS avg_age, ROUND(AVG(TIMESTAMPDIFF(YEAR, hire_date, CURDATE())), 1) AS avg_tenure FROM employees UNION ALL SELECT CONCAT(department, '部门') AS category, COUNT(*) AS employee_count, CONCAT('¥', FORMAT(AVG(salary), 2)) AS avg_salary, CONCAT('¥', FORMAT(MIN(salary), 2)) AS min_salary, CONCAT('¥', FORMAT(MAX(salary), 2)) AS max_salary, ROUND(AVG(TIMESTAMPDIFF(YEAR, birth_date, CURDATE())), 1) AS avg_age, ROUND(AVG(TIMESTAMPDIFF(YEAR, hire_date, CURDATE())), 1) AS avg_tenure FROM employees GROUP BY department ORDER BY category; -- 2. 月度入职统计 SELECT YEAR(hire_date) AS hire_year, MONTH(hire_date) AS hire_month, MONTHNAME(hire_date) AS month_name, COUNT(*) AS new_hires, GROUP_CONCAT(CONCAT(first_name, ' ', last_name) SEPARATOR ', ') AS new_employees, ROUND(AVG(salary), 2) AS avg_starting_salary FROM employees GROUP BY YEAR(hire_date), MONTH(hire_date) ORDER BY hire_year DESC, hire_month DESC; -- 3. 薪资分布分析 SELECT CASE WHEN salary < 7000 THEN '< 7K' WHEN salary < 8000 THEN '7K-8K' WHEN salary < 9000 THEN '8K-9K' WHEN salary < 10000 THEN '9K-10K' ELSE '> 10K' END AS salary_range, COUNT(*) AS employee_count, ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM employees), 2) AS percentage, GROUP_CONCAT(department ORDER BY department SEPARATOR ', ') AS departments FROM employees GROUP BY CASE WHEN salary < 7000 THEN '< 7K' WHEN salary < 8000 THEN '7K-8K' WHEN salary < 9000 THEN '8K-9K' WHEN salary < 10000 THEN '9K-10K' ELSE '> 10K' END ORDER BY MIN(salary);

业务逻辑处理

-- 1. 员工绩效评估 SELECT CONCAT(first_name, ' ', last_name) AS employee_name, department, salary, TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) AS years_of_service, CASE WHEN salary >= 10000 AND TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) >= 3 THEN 'A+' WHEN salary >= 9000 AND TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) >= 2 THEN 'A' WHEN salary >= 8000 OR TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) >= 3 THEN 'B+' WHEN salary >= 7000 OR TIMESTAMPDIFF(YEAR, hire_date, CURDATE()) >= 1 THEN 'B' ELSE 'C' END AS performance_grade, CASE WHEN salary < (SELECT AVG(salary) FROM employees e2 WHERE e2.department = employees.department) * 0.8 THEN '需要关注' WHEN salary > (SELECT AVG(salary) FROM employees e2 WHERE e2.department = employees.department) * 1.2 THEN '表现优秀' ELSE '表现正常' END AS salary_status, DATE_ADD(hire_date, INTERVAL 1 YEAR) AS first_review_date, DATE_ADD(hire_date, INTERVAL 5 YEAR) AS five_year_milestone FROM employees ORDER BY performance_grade, salary DESC; -- 2. 产品库存预警 SELECT product_name, category, stock_quantity, price, stock_quantity * price AS inventory_value, CASE WHEN stock_quantity = 0 THEN '缺货' WHEN stock_quantity <= 10 THEN '库存不足' WHEN stock_quantity <= 30 THEN '库存偏低' ELSE '库存充足' END AS stock_status, CASE WHEN stock_quantity <= 10 THEN '紧急补货' WHEN stock_quantity <= 30 THEN '计划补货' ELSE '无需补货' END AS restock_action, GREATEST(50 - stock_quantity, 0) AS suggested_restock_quantity FROM products ORDER BY stock_quantity ASC, inventory_value DESC;

函数性能优化

🚀 性能优化建议

  • 避免在WHERE子句中使用函数:会导致索引失效
  • 合理使用聚合函数:配合适当的索引提高查询效率
  • 字符串函数优化:大量数据时考虑在应用层处理
  • 日期函数缓存:重复计算的日期可以预先计算存储

⚠️ 常见陷阱

  • NULL值处理:函数遇到NULL通常返回NULL
  • 数据类型转换:隐式转换可能影响性能
  • 字符集问题:字符串函数受字符集影响
  • 时区问题:日期时间函数要注意时区设置
-- 性能对比示例 -- 不推荐:在WHERE中使用函数 SELECT * FROM employees WHERE YEAR(hire_date) = 2020; -- 推荐:使用范围查询 SELECT * FROM employees WHERE hire_date >= '2020-01-01' AND hire_date < '2021-01-01'; -- 不推荐:重复计算 SELECT first_name, TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) AS age, CASE WHEN TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) >= 30 THEN '成熟' ELSE '年轻' END FROM employees; -- 推荐:使用变量或子查询 SELECT first_name, age, CASE WHEN age >= 30 THEN '成熟' ELSE '年轻' END AS age_group FROM ( SELECT first_name, TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) AS age FROM employees ) AS emp_with_age;

总结

MySQL函数是数据处理的强大工具,合理使用可以大大简化查询逻辑,提高开发效率。掌握各类函数的特点和使用场景,是成为MySQL专家的必经之路。

🎯 学习建议

  • 分类学习:按功能分类逐步掌握各类函数
  • 实践应用:在实际项目中多使用函数解决问题
  • 性能意识:时刻关注函数对查询性能的影响
  • 版本差异:了解不同MySQL版本的函数差异
  • 组合使用:学会组合多个函数解决复杂问题

📚 扩展学习

  • 自定义函数:学习创建用户定义函数(UDF)
  • 存储过程:在存储过程中使用函数
  • 触发器:在触发器中应用函数
  • 视图:在视图定义中使用函数