在日常 MySQL 数据查询中,我们常常需要基于表中现有字段生成新的计算结果(比如拼接姓名与性别、计算年龄差值、汇总数值等),这些动态生成的结果就是计算字段。计算字段不会存储在数据表中,而是在查询时实时计算,是提升数据查询灵活性的核心技巧。
本文将手把手教你掌握计算字段的核心用法。
计算字段是通过对数据表中现有字段进行函数处理、算术运算、字符串拼接等操作,在SELECT查询中动态生成的虚拟字段。它的核心价值在于:无需修改数据表结构,就能按需生成业务所需的新数据,比如将 “姓名” 和 “性别” 拼接成 “用户昵称”,或基于 “年龄” 计算 “出生年份”。
拼接字段是最常用的计算字段场景之一,比如将 “姓名” 和 “性别” 拼接成 “用户全称”,或将 “姓名” 和 “地址” 拼接成 “用户描述”。
在 MySQL 中主要通过CONCAT()函数实现拼接(注意:若拼接的字段包含NULL,结果会直接为NULL,可通过COALESCE()处理)。
查询用户的 “姓名 + 性别” 组合(比如 “张三(男)”),并自定义字段名为user_fullname。如下:
> SELECT CONCAT(name, '(', gender, ')') AS user_fullname,phone FROM `user` user_fullname|phone | -------------+-----------+ 张三(男) |13800138000| 李四(女) |13800138001| 王五(男) |13800138002| 赵六(女) |13800138003| 孙七(男) |13800138004| 周八(女) |13800138005| |13800138006| 郑十(女) |13800138007| 钱十一(男) |13800138008| 孙十二(女) |13800138009| 10 row(s) fetched.
注意,上面 “|13800138006|” 行因为性别 “gender” 为 NULL,因此拼接结果为 NULL。
将性别为NULL的用户默认显示为 “未知”,再拼接姓名。如下:
> SELECT CONCAT(name, '(', COALESCE(gender, '未知'), ')') AS user_fullname,age FROM `user` user_fullname|age| -------------+---+ 张三(男) | 25| 李四(女) | 30| 王五(男) | 28| 赵六(女) | 22| 孙七(男) | 35| 周八(女) | 27| 吴九(未知) | 32| 郑十(女) | 29| 钱十一(男) | 24| 孙十二(女) | 31| 10 row(s) fetched.
算术计算是计算字段的另一核心场景,支持+(加)、-(减)、*(乘)、/(除)、%(取余)等运算符,常用于数值字段的计算(比如年龄、金额、数量等)。
假设当前年份是 2025 年,根据用户年龄计算出生年份(出生年份 = 2025 - 年龄)。
> SELECT name,age,2025-age AS birth_year FROM `user` name|age|birth_year| ----+---+----------+ 张三 | 25| 2000| 李四 | 30| 1995| 王五 | 28| 1997| 赵六 | 22| 2003| 孙七 | 35| 1990| 周八 | 27| 1998| 吴九 | 32| 1993| 郑十 | 29| 1996| 钱十一 | 24| 2001| 孙十二 | 31| 1994| 10 row(s) fetched.
注意,上述输出中 “birth_year” 是用户的出生日期。
先计算所有用户的平均年龄,再查询每个用户的年龄与平均年龄的差值。
-- 第一步:计算平均年龄(约28.4岁) > SELECT AVG(age) AS avg_age FROM `user` avg_age| -------+ 28.3000| 1 row(s) fetched. -- 第二步:计算每个用户与平均年龄的差值 -- ROUND() 保留1位小数 > SELECT name,age,ROUND(age - (SELECT AVG(age) FROM `user`), 1) AS age_diff FROM `user` name|age|age_diff| ----+---+--------+ 张三 | 25| -3.3| 李四 | 30| 1.7| 王五 | 28| -0.3| 赵六 | 22| -6.3| 孙七 | 35| 6.7| 周八 | 27| -1.3| 吴九 | 32| 3.7| 郑十 | 29| 0.7| 钱十一 | 24| -4.3| 孙十二 | 31| 2.7| 10 row(s) fetched.
将用户按年龄分组(20-29 岁、30-39 岁),通过算术运算生成分组标识。
> SELECT name,age,CONCAT(FLOOR(age/10)*10, '-', (FLOOR(age/10)+1)*10-1, '岁') AS age_group FROM `user` name|age|age_group| ----+---+---------+ 张三 | 25|20-29岁 | 李四 | 30|30-39岁 | 王五 | 28|20-29岁 | 赵六 | 22|20-29岁 | 孙七 | 35|30-39岁 | 周八 | 27|20-29岁 | 吴九 | 32|30-39岁 | 郑十 | 29|20-29岁 | 钱十一 | 24|20-29岁 | 孙十二 | 31|30-39岁 | 10 row(s) fetched.
筛选出年龄大于所有用户平均年龄的用户,并计算其年龄超出的部分。
> SELECT name, age, age-(SELECT AVG(age) FROM `user`) AS exceed_age FROM `user` WHERE age > (SELECT AVG(age) FROM `user`) name|age|exceed_age| ----+---+----------+ 李四 | 30| 1.7000| 孙七 | 35| 6.7000| 吴九 | 32| 3.7000| 郑十 | 29| 0.7000| 孙十二 | 31| 2.7000| 5 row(s) fetched.