# 找到昵称满足的,c开头的试卷, # 计算按用户和试卷分组的均分 SELECT uid, exam_id, ROUND(AVG(avg_score), 0) avg_score FROM ( # 设为子查询是因为不能在这里对其分组 SELECT uid, exam_id, AVG(score) OVER(PARTITION BY uid, exam_id) avg_score FROM exam_record a JOIN user_info b USING(uid) JOIN examination_info c USING(exam_id) WHERE (nick_name LIKE '牛客%号' OR nick_name/2 > 0) AND (tag LIKE 'C%' OR tag LIKE 'c%')# WHERE LOWER(tag) LIKE 'c%' #使用该函数会更简洁 ORDER BY uid, avg_score ) a GROUP BY uid, exam_id HAVING avg_score IS NOT NULL
踩的坑:限制条件这里,最开始没有用圆括号,导致第一个or就使得第一个条件符合的就行了
在 SQL 中,AND
和 OR
是逻辑运算符,它们用来组合多个条件。AND
操作符表示所有条件都必须为真,才会选择记录;而 OR
操作符表示只要任一条件为真,就会选择记录。重要的是,AND
操作符的优先级高于 OR
操作符。
让我们来对比一下您给出的两个 WHERE
子句:
有括号的条件:
WHERE (nick_name LIKE '牛客%号' OR nick_name/2 > 0) AND (tag LIKE 'C%' OR tag LIKE 'c%')
- 这个查询首先计算括号内的条件,然后使用
AND
运算符组合结果。 - 只有当
nick_name
字段以 '牛客' 开头并以 '号' 结尾或者nick_name/2
的结果大于 0,且同时tag
字段以大写或小写的 'C' 开头时,记录才会被选中。
没有括号的条件:
WHERE nick_name LIKE '牛客%号' OR nick_name/2 > 0 AND tag LIKE 'C%' OR tag LIKE 'c%'
- 在没有括号的情况下,
AND
运算符将首先被计算。 - 所以
nick_name/2 > 0 AND tag LIKE 'C%'
会首先被评估,然后结果会与其他OR
条件组合。 - 这可能会导致不同的结果集,因为没有明确的分组指示 SQL 如何组合这些条件。
为了更清楚地理解两者之间的区别,让我们分解第二个条件:
- 如果
nick_name
字段以 '牛客' 开头并以 '号' 结尾,那么记录会被选中,无论tag
字段的值是什么。 - 如果
nick_name/2
的结果大于 0 且tag
字段以大写 'C' 开头,那么记录会被选中。 - 如果
tag
字段以小写 'c' 开头,那么记录会被选中,无论nick_name
的值是什么。
可以看出,没有使用括号的查询可能会因为 OR
和 AND
的优先级问题而返回更多的记录。
通常来说,使用括号来明确指定条件的逻辑组合是一个好习惯,因为它可以避免混淆,并确保条件的执行顺序与你的意图相符。
使用窗口函数时不需要 GROUP BY
:窗口函数会在保持原始行数不变的情况下为每行添加一个计算列。因此,如果您尝试在窗口函数的查询中同时使用 GROUP BY
,您可能会收到一个错误,因为 GROUP BY
会尝试对结果集进行聚合。
新知识点:
1、在大多数SQL数据库中,字符串比较默认是区分大小写的。但是,你可以通过使用不区分大小写的比较来简化这个条件。根据你使用的数据库系统,有几种方法可以实现不区分大小写的搜索。
SQL标准方法
大多数数据库都支持 ILIKE
关键字,或者 LOWER()
函数来进行不区分大小写的比较:
使用 ILIKE
(这通常在 PostgreSQL 中可用):
WHERE tag ILIKE 'c%'
使用 LOWER()
函数:
WHERE LOWER(tag) LIKE 'c%'
这两种方法都会找到以 'C' 或 'c' 开头的 tag
值。
MySQL
在 MySQL 中,你可以使用 COLLATE
来指定在比较时使用的字符集和校对规则,例如:
WHERE tag COLLATE utf8_general_ci LIKE 'c%'
这里 utf8_general_ci
是一个不区分大小写的校对规则,ci 表示 case-insensitive(不区分大小写)。
SQL Server
在 SQL Server 中,你需要查看列的校对顺序设置。如果它被设置为不区分大小写(例如 SQL_Latin1_General_CP1_CI_AS
),你可以直接使用:
WHERE tag LIKE 'c%'
并且它会返回所有以 'C' 或 'c' 开头的 tag
值。
Oracle
在 Oracle 中,默认情况下字符串比较是区分大小写的,但你可以使用 UPPER()
或 LOWER()
函数来进行不区分大小写的比较:
WHERE LOWER(tag) LIKE 'c%'
在编写你的查询时,请根据你所使用的数据库系统选择适当的方法。如果你不确定数据库的默认大小写敏感性或者校对规则设置,使用 LOWER()
或 UPPER()
函数是一个可靠的选择,因为它们在所有主流数据库系统中都是可用的。
2、在 MySQL 中,要判断一个字段的值是否为纯数字,您不能直接使用 nick_name/2 > 0
,因为如果 nick_name
是一个包含非数字字符的字符串,这样的除法操作会导致错误或者返回 NULL。
相反,您可以使用正则表达式来检查一个字段是否只包含数字。在 MySQL 中,您可以使用 REGEXP
来进行正则匹配:
SELECT * FROM table_name WHERE column_name REGEXP '^[0-9]+$';
这条 SQL 语句会选择 column_name
字段中只包含数字的所有记录。这里的正则表达式 '^[0-9]+$'
的含义是:
^
:匹配字符串的开始[0-9]+
:匹配一个或多个数字$
:匹配字符串的结束
结合在一起,这个正则表达式匹配从开始到结束的整个字符串,确保字符串中没有其他字符,只有数字。
在 MySQL 8.0+ 中,您也可以使用 RLIKE
,它是 REGEXP
的同义词:
SELECT * FROM table_name WHERE column_name RLIKE '^[0-9]+$';
如果您使用的是早期版本的 MySQL,您可能需要使用不同的正则表达式语法或函数。请根据您的 MySQL 版本进行调整。