
SELECT
COUNT(*) AS male_num,
ROUND (AVG(gpa),1) AS avg_gpa
FROM user_profile
WHERE gender = 'male';
COUNT(*)是一个整体,
COUNT 与 (*)之间不要加空格
因为有些OJ平台会将COUNT (*)判为格式错误
要求使用标准COUNT(*)写法
SELECT device_id, gender, age, university
FROM user_profile
WHERE age != NULL; -- 这也是错误的写法!
为什么仍然错误?
- NULL 的特殊性:在 SQL 中,任何与 NULL 的比较运算(包括
=、!=、>、<等)都会返回 UNKNOWN,而不是 TRUE 或 FALSE - WHERE 子句:只会返回条件判断为 TRUE 的行,而 UNKNOWN 会被当作 FALSE 处理
正确写法:
必须使用专门的 IS NOT NULL 操作符:
-- 正确写法 ✅
SELECT device_id, gender, age, university
FROM user_profile
WHERE age IS NOT NULL;
对比实验:
假设数据:
| device_id | age |
|-----------|-----|
| 10001 | 20 |
| 10002 | NULL|
你的错误写法:
SELECT * FROM user_profile WHERE age != NULL;
-- 返回:空结果(不会返回 10001)
正确写法:
SELECT * FROM user_profile WHERE age IS NOT NULL;
-- 返回:10001 | 20
记忆技巧:
把 NULL 想象成一个"黑洞":
- 任何与 NULL 的常规比较都会被"吞噬"(变成 UNKNOWN)
- 必须用专门的"手电筒"(
IS NULL/IS NOT NULL)才能检测它
进阶知识:
如果确实需要与其他值一起比较 NULL,可以:
-- 查询 age 不是 20 的记录(包括 NULL)
SELECT * FROM user_profile WHERE age != 20 OR age IS NULL;
-- MySQL 专用简写(非标准语法):
SELECT * FROM user_profile WHERE age <=> NULL; -- 等价于 IS NULL
通俗易懂讲解 SQL 中的 IN 和 NOT IN
1. IN 操作符:相当于"属于"
比喻:
就像老师问:“哪些同学是来自北京、上海或广州的?” —— 这就是 IN 的用法
作用:
检查某个值是否在一组给定的值中
基本语法:
SELECT 列名 FROM 表名
WHERE 列名 IN (值1, 值2, 值3,...);
实际例子:
-- 查询来自北京大学、清华大学或复旦大学的学生
SELECT device_id, university
FROM user_profile
WHERE university IN ('北京大学', '清华大学', '复旦大学');
等价写法:
-- 上面的IN查询等价于多个OR条件
SELECT device_id, university
FROM user_profile
WHERE university = '北京大学'
OR university = '清华大学'
OR university = '复旦大学';
特点:
- 比多个
OR条件更简洁 - 可以包含很多值(几十上百个都行)
- 执行效率通常比多个
OR更高
2. NOT IN 操作符:相当于"不属于"
比喻:
就像老师说:“除了迟到的小明、小红,其他同学都可以参加活动” —— 这就是 NOT IN 的用法
作用:
检查某个值是否不在一组给定的值中
基本语法:
SELECT 列名 FROM 表名
WHERE 列名 NOT IN (值1, 值2, 值3,...);
实际例子:
-- 查询不是来自北京、上海或广州的学生
SELECT device_id, university
FROM user_profile
WHERE university NOT IN ('北京大学', '清华大学', '复旦大学');
等价写法:
-- 上面的NOT IN查询等价于多个AND条件
SELECT device_id, university
FROM user_profile
WHERE university != '北京大学'
AND university != '清华大学'
AND university != '复旦大学';
3. 重要注意事项
NULL 值问题:
-- 如果NOT IN列表中有NULL值,整个查询会返回空结果!
SELECT * FROM table WHERE col NOT IN (1, 2, NULL); -- 错误示范
-- 正确做法:先处理NULL值
SELECT * FROM table
WHERE col NOT IN (1, 2) AND col IS NOT NULL;
性能建议:
- 当列表值很多时(如超过100个),考虑改用临时表或JOIN
- 对大型表,确保相关列有索引
4. 实际应用场景
IN 的典型用途:
- 查找特定类别的商品
- 筛选来自某些地区的用户
- 选择特定状态(如"已支付"、“已发货”)的订单
NOT IN 的典型用途:
- 排除黑名单用户
- 查找未完成的订单
- 筛选不在某些部门的员工
5. 扩展用法
子查询中使用:
-- 查找有订单的用户
SELECT * FROM customers
WHERE id IN (SELECT customer_id FROM orders);
-- 查找没有订单的用户
SELECT * FROM customers
WHERE id NOT IN (SELECT customer_id FROM orders);
与其他条件组合:
-- 25岁以上且来自特定学校的学生
SELECT * FROM user_profile
WHERE age > 25
AND university IN ('北京大学', '清华大学');
记住:IN 是"属于这些",NOT IN 是"不属于这些",就像集合的"包含"和"不包含"关系!
你的 SQL 查询语句中的括号使用是 正确且必要的,但最后的 DESC 放错位置了。以下是修正和建议:
修正后的查询:
SELECT device_id, gender, age, university, gpa
FROM user_profile
WHERE (gpa > 3.5 AND university = '山东大学')
OR (gpa > 3.8 AND university = '复旦大学')
ORDER BY gpa DESC; -- DESC 应该放在 ORDER BY 子句中
关于括号的说明:
-
你的括号逻辑完全正确:
- 清晰划分了两种条件组合:
(条件A AND 条件B) OR (条件C AND 条件D) - 不加括号会改变运算优先级(AND 优先级高于 OR)
- 清晰划分了两种条件组合:
-
等价的无括号写法(不推荐,可读性差):
WHERE gpa > 3.5 AND university = '山东大学' OR gpa > 3.8 AND university = '复旦大学'
常见改进建议:
-
添加缩进提升可读性:
SELECT device_id, gender, age, university, gpa FROM user_profile WHERE (gpa > 3.5 AND university = '山东大学') OR (gpa > 3.8 AND university = '复旦大学') ORDER BY gpa DESC; -
如果条件更复杂,可以用注释说明:
WHERE /* 山东大学学生且GPA>3.5 */ (gpa > 3.5 AND university = '山东大学') OR /* 复旦大学学生且GPA>3.8 */ (gpa > 3.8 AND university = '复旦大学') -
其他等效写法(使用 IN + CASE WHEN):
WHERE university IN ('山东大学', '复旦大学') AND gpa > CASE WHEN university = '山东大学' THEN 3.5 WHEN university = '复旦大学' THEN 3.8 END
为什么你的原查询报错?
DESC是排序方向关键字,必须配合ORDER BY使用- 错误写法:
WHERE ... DESC❌ - 正确写法:
ORDER BY column_name DESC✅
你的 SQL 查询语句是:
SELECT device_id, age, university
FROM user_profile
WHERE university LIKE '北京%';
查询解析:
- 功能:查询大学名称以"北京"开头的用户的设备ID、年龄和大学信息
- 关键点:
LIKE '北京%':%是通配符,表示匹配"北京"开头的任意字符串- 例如会匹配:“北京大学”、"北京理工大学"等
预期结果:
假设数据:
+-----------+-----+--------------+
| device_id | age | university |
+-----------+-----+--------------+
| 10001 | 20 | 北京大学 |
| 10002 | 21 | 清华大学 |
| 10003 | 22 | 北京理工大学 |
| 10004 | 23 | 复旦大学 |
+-----------+-----+--------------+
查询结果:
+-----------+-----+--------------+
| device_id | age | university |
+-----------+-----+--------------+
| 10001 | 20 | 北京大学 |
| 10003 | 22 | 北京理工大学 |
+-----------+-----+--------------+
其他常用通配符:
-
_:匹配单个字符-- 匹配"北京"开头且只有4个字的大学(如:北京大学) WHERE university LIKE '北京__' -
%:匹配任意长度字符(包括0个)-- 匹配包含"北京"的大学(如:北京大学、中国北京学院) WHERE university LIKE '%北京%' -
组合使用:
-- 匹配以"北京"开头,以"大学"结尾的学校 WHERE university LIKE '北京%大学'
性能建议:
LIKE '北京%'可以使用索引(前缀匹配)LIKE '%北京%'通常无法使用索引,大数据量时性能较差- 如果经常需要这种查询,可以考虑全文索引
SELECT MAX(gpa)
FROM user_profile;
查询解析:
- 功能:查找
user_profile表中gpa字段的最大值 - 关键点:
MAX()是聚合函数,返回指定列的最大值- 会扫描所有行的
gpa值(自动忽略 NULL 值)
预期结果:
假设数据:
+------+
| gpa |
+------+
| 3.2 |
| 3.8 |
| 4.0 |
| NULL |
| 3.5 |
+------+
查询将返回:
+----------+
| MAX(gpa) |
+----------+
| 4.0 |
+----------+
SQL ROUND(MAX(gpa), 1) AS gpa 语法详解
这个表达式由三个关键部分组成,我将逐一详细解释:
1. MAX(gpa) - 聚合函数
- 功能:从
gpa列中找出最大值 - 特点:
- 自动忽略 NULL 值
- 如果所有值都是 NULL,返回 NULL
- 示例:
-- 假设数据: 3.2, 3.8, 4.0, NULL SELECT MAX(gpa) FROM user_profile; -- 返回: 4.0
2. ROUND(数值, 小数位数) - 四舍五入函数
- 参数:
- 第一个参数:要舍入的数值(这里是
MAX(gpa)的结果) - 第二个参数:保留的小数位数(这里是 1)
- 第一个参数:要舍入的数值(这里是
- 舍入规则:
- 标准四舍五入
- 如果恰好是中间值(如 3.25 保留1位),不同数据库可能处理不同
- 示例:
SELECT ROUND(3.14159, 1); -- 返回 3.1 SELECT ROUND(3.85, 1); -- 返回 3.9
3. AS gpa - 列别名
- 作用:为计算结果列指定显示名称
- 特点:
AS关键字可省略(SELECT MAX(gpa) gpa)- 当列名包含空格或特殊字符时必须用引号:
SELECT MAX(gpa) AS '最高 GPA' FROM user_profile;
完整执行流程
- 先执行
MAX(gpa)找出最大值(如 3.82) - 然后执行
ROUND(3.82, 1)得到 3.8 - 最后将结果列命名为
gpa
常见变体
-
不同数据库的差异:
-- MySQL/PostgreSQL SELECT ROUND(MAX(gpa), 1) AS gpa; -- SQL Server SELECT ROUND(MAX(gpa), 1, 1) AS gpa; -- 第三个参数控制舍入方式 -
其他舍入方式:
-- 向上取整 SELECT CEILING(MAX(gpa)) AS gpa; -- 向下取整 SELECT FLOOR(MAX(gpa)) AS gpa; -- 截断小数位 SELECT TRUNCATE(MAX(gpa), 1) AS gpa; -- MySQL -
格式化输出:
-- 返回字符串类型 SELECT FORMAT(MAX(gpa), 1) AS gpa; -- MySQL
要查询复旦大学学生的最高 GPA 并保留到小数点后1位,可以使用以下 SQL 查询:
SELECT ROUND(MAX(gpa), 1) AS gpa
FROM user_profile
WHERE university = '复旦大学';
查询解析:
WHERE university = '复旦大学'- 筛选复旦大学的学生记录MAX(gpa)- 计算这些学生的最大 GPA 值ROUND(..., 1)- 将结果四舍五入到小数点后1位AS gpa- 将结果列命名为 gpa(与题目要求的输出一致)
预期结果:
+------+
| gpa |
+------+
| 3.8 |
+------+
8297

被折叠的 条评论
为什么被折叠?



