SQL进阶必备:从计算字段到多表联结,让查询效率翻倍!
一、创建计算字段:让数据“按需重组”
存储在数据库中的原始数据,往往不符合直接使用的格式(比如分散在多列的信息、需要计算的数值),这时候“计算字段”就能派上用场——它不是表中实际存在的列,而是运行时通过SQL语句动态创建的虚拟列。
1. 核心用法:拼接与算术运算
- 字段拼接:用
Concat()函数将多列数据合并为一个字段,比如将供应商名称和国家拼接成“名称(国家)”格式:
其中SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')') AS vend_title FROM vendors;RTrim()用于去除字段右侧多余空格,AS给计算字段起别名(别名是客户机引用该列的关键)。 - 算术计算:直接对数值型字段进行加减乘除运算,比如计算订单中每项物品的总金额(单价×数量):
SELECT prod_id, quantity, item_price, quantity * item_price AS expanded_price FROM orderitems WHERE order_num = 20005;
2. 关键技巧:别名的正确使用
别名不仅能简化计算字段的引用,还能解决列名含特殊字符、名称不清晰的问题。命名时建议简洁明了,比如用total_price代替quantity*item_price,让SQL语句更易读。
二、数据处理函数:给数据“做精加工”
函数是SQL处理数据的“工具箱”,能快速完成文本格式化、日期计算、数值转换等操作。MySQL支持文本、日期时间、数值三类常用函数,重点掌握这些高频用法:
1. 文本处理函数:搞定字符串格式
- 大小写转换:
Upper()(转大写)、Lower()(转小写) - 截取与查找:
Left()(取左侧字符)、Locate()(查找子串位置) - 去空格:
Trim()(去除首尾空格)、RTrim()(去除右侧空格) - 语音匹配:
Soundex()(按发音匹配字符串,比如匹配“Y.Lee”和“Y.Lie”):SELECT cust_name FROM customers WHERE Soundex(cust_contact) = Soundex('Y Lie');
2. 日期时间函数:精准处理时间数据
日期是SQL查询中高频过滤条件,核心函数用法如下:
- 获取当前时间:
Now()(日期+时间)、CurDate()(仅日期) - 提取日期成分:
Year()(年份)、Month()(月份)、Day()(天数) - 日期比较:用
Date()函数忽略时间部分,只对比日期:SELECT cust_id FROM orders WHERE Date(order_date) = '2005-09-01';
3. 数值处理函数:简化数学运算
常用函数包括Abs()(绝对值)、Rand()(随机数)、Sum()(求和)等,多用于数值型数据的统计与转换。
三、汇总数据:用聚集函数快速统计
当需要对数据进行统计分析(比如求平均值、计数、找最值)时,不需要逐行检索数据,直接用聚集函数就能快速得到结果。
1. 5个核心聚集函数
| 函数 | 功能 |
|---|---|
AVG() |
返回某列平均值(忽略NULL值) |
COUNT() |
统计行数(COUNT(*)含NULL,COUNT(列名)不含NULL) |
MAX() |
返回某列最大值 |
MIN() |
返回某列最小值 |
SUM() |
返回某列值之和 |
2. 实用示例
- 计算所有产品的平均价格:
SELECT AVG(prod_price) AS avg_price FROM products; - 统计有电子邮件的客户数量:
SELECT COUNT(cust_email) AS num_cust FROM customers; - 合计某订单的总金额:
SELECT SUM(quantity * item_price) AS total FROM orderitems WHERE order_num = 20005;
四、分组数据:按条件分类统计
汇总函数默认对整个表生效,而GROUP BY子句能将数据按指定列分组,让聚集函数对每个组单独计算,比如“统计每个供应商的产品数量”“每个客户的订单数”。
1. 基础用法:GROUP BY + 聚集函数
SELECT vend_id, COUNT(*) AS num_prods
FROM products GROUP BY vend_id;
该语句按vend_id分组,统计每个供应商的产品数量。
2. 关键补充:HAVING过滤分组
WHERE用于过滤行,HAVING用于过滤分组(只能跟在GROUP BY后)。比如筛选出产品数量≥2且单价≥10的供应商:
SELECT vend_id, COUNT(*) AS num_prods
FROM products WHERE prod_price >= 10
GROUP BY vend_id HAVING COUNT(*) >= 2;
3. 注意事项
GROUP BY后列出的列,必须是SELECT中的非聚集列(或表达式);- 分组后如需排序,需加
ORDER BY(GROUP BY不保证分组顺序)。
五、子查询:用“查询嵌套”解决复杂问题
子查询(嵌套查询)是将一个查询结果作为另一个查询的条件或字段,适合解决“多步骤”的数据检索,比如“找出订购了某产品的所有客户”。
1. 核心场景:WHERE子句中的子查询
比如查找订购了产品TNT2的客户名称,需分3步:①找含TNT2的订单号→②找这些订单对应的客户ID→③找客户ID对应的客户信息,用子查询可合并为一条语句:
SELECT cust_name FROM customers
WHERE cust_id IN (
SELECT cust_id FROM orders
WHERE order_num IN (
SELECT order_num FROM orderitems WHERE prod_id = 'TNT2'
)
);
2. 进阶用法:作为计算字段的子查询
比如统计每个客户的订单总数,将子查询作为计算字段:
SELECT cust_name,
(SELECT COUNT(*) FROM orders WHERE orders.cust_id = customers.cust_id) AS orders
FROM customers;
这种“相关子查询”会对外部查询的每一行执行一次内部查询,需注意列名的完全限定(比如orders.cust_id),避免歧义。
六、联结表:打破数据孤岛(重点!)
关系数据库中,数据被分散存储在多个表中(比如客户表、订单表、产品表),联结(JOIN)是将这些表按关联关系组合查询的核心技术,也是SQL最强大的功能之一。
1. 先搞懂:为什么需要联结?
比如要查询“客户名称+订单号+订购产品”,这些信息分散在customers、orders、orderitems三个表中,只有通过联结才能一次性检索,避免数据重复存储(比如客户信息不会在每个订单中重复)。
2. 基础联结:内部联结(等值联结)
最常用的联结方式,通过两表中相同的列(比如vendors.vend_id和products.vend_id)匹配数据:
SELECT vend_name, prod_name, prod_price
FROM vendors, products
WHERE vendors.vend_id = products.vend_id;
或用标准SQL的INNER JOIN语法(更清晰,推荐使用):
SELECT vend_name, prod_name, prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;
3. 关键提醒:避免笛卡儿积
如果联结时忘记写WHERE或ON条件,MySQL会返回两表的“笛卡儿积”(行数=表1行数×表2行数),导致数据冗余且无意义,一定要注意!
4. 多表联结示例
查询订单20005的客户名称、产品名和数量,需联结3个表:
SELECT cust_name, prod_name, quantity
FROM customers, orders, orderitems
WHERE customers.cust_id = orders.cust_id
AND orderitems.order_num = orders.order_num
AND orderitems.order_num = 20005;
总结:SQL进阶的核心逻辑
这6章内容层层递进,从“处理单表数据”(计算字段、函数),到“统计单表数据”(汇总、分组),再到“跨表关联数据”(子查询、联结),本质是逐步提升数据处理的“维度”和“灵活性”。
浙公网安备 33010602011771号