MySQL聚合函数|逻辑运算符
MySQL聚合函数和逻辑运算符都是在处理数据库查询时非常重要的工具。聚合函数用于对一组数据进行统计计算,生成单个汇总值,而逻辑运算符则用于对布尔表达式进行判断,以确定查询条件的逻辑关系。当需要在查询中同时使用聚合函数和逻辑运算符时,理解它们的混合使用方式以及运算顺序至关重要。以下是对这些概念的详细解释,以及运算顺序的详解:
MySQL 聚合函数
MySQL 支持多种聚合函数,包括但不限于:
- COUNT():返回指定列中非NULL值的行数。
- SUM():计算指定列中所有数值的总和。
- AVG():计算指定列中所有数值的平均值。
- MAX():返回指定列中的最大值。
- MIN():返回指定列中的最小值。
例如:
SELECT COUNT(*), AVG(salary), MAX(sales), MIN(price)
FROM employees;
上述查询将分别计算 employees
表中的总行数、员工薪资的平均值、最大销售额和最低价格。
MySQL 逻辑运算符
MySQL 中的逻辑运算符主要包括:
- NOT 或 !:逻辑非,否定其后的表达式。如果表达式为真(1),则结果为假(0);若为假(0)或 NULL,则结果为真(1)。
- AND 或 &&:逻辑与,当两边的表达式都为真时结果才为真,否则为假。
- OR或者||:逻辑或,只要两边的表达式中有一个为真,结果就为真;只有两边都为假时结果才为假。
例如:
SELECT * FROM orders
WHERE status = 'completed' AND payment_received = 1 OR customer_id = 100;
此查询将选择状态为“completed”,已收到付款或客户ID为100的所有订单。
逻辑运算符混合使用及运算顺序
在使用逻辑运算符时,遵循特定的运算优先级和结合性规则,这对于正确构建复杂的查询条件至关重要。根据MySQL的运算符优先级,逻辑运算符的优先级从高到低排列如下:
- NOT(逻辑非)
- AND(逻辑与)
- OR(逻辑或)
这意味着:
- NOT 最先被计算。
- 同一优先级的运算符(如多个 AND 或多个 OR)按照从左到右的顺序(即结合性)进行计算。
- 当不同优先级的运算符混合使用时,高优先级运算符先于低优先级运算符执行。
例如,对于以下查询:
SELECT * FROM products
WHERE price > 100 AND (category = 'Electronics' OR brand = 'Apple');
运算顺序如下:
- 首先,评估括号内的条件
(category = 'Electronics' OR brand = 'Apple')
。 - 其次,将得到的结果与
price > 100
使用AND
运算符进行组合。
如果希望改变默认的运算顺序,可以使用括号明确指定优先级,如上述示例中的括号确保了 OR
运算先于外部的 AND
运算进行。
当遇到不带括号的复合条件表达式 price > 100 AND category = 'Electronics' OR brand = 'Apple'
,要理解其实际运算顺序,需要依据MySQL的逻辑运算符优先级规则。由于没有括号来明确指定优先级,根据优先级从高到低的顺序(NOT -> AND -> OR),运算过程如下:
-
优先级规则:
AND
的优先级高于OR
。- 没有括号的情况下,从左到右依次计算。
-
实际运算步骤:
首先,由于
AND
的优先级较高,会先计算左侧的price > 100
与category = 'Electronics'
之间的逻辑关系:(price > 100 AND category = 'Electronics')
然后,这个结果作为一个整体与右侧的
brand = 'Apple'
通过OR
运算符进行组合:(price > 100 AND category = 'Electronics') OR brand = 'Apple'
这意味着查询将返回以下三类记录:
- 价格大于100且类别为“Electronics”的产品。
- 品牌为“Apple”的产品(不论价格和类别如何)。
注意:此处的运算顺序可能会导致非预期结果,因为
AND
优先级高,它将首先对price > 100
和category = 'Electronics'
两部分进行联合筛选,然后再将这一结果与其他满足brand = 'Apple'
的记录合并。这可能会包括一些不符合原意的记录,比如价格低于100但品牌为“Apple”的产品。如果意图筛选出同时满足以下条件之一的产品:
- 价格大于100且类别为“Electronics”;
- 或者品牌为“Apple”。
那么正确的写法应该使用括号来确保
OR
运算的优先级:price > 100 AND (category = 'Electronics' OR brand = 'Apple')
或者:
(price > 100 AND category = 'Electronics') OR (price > 100 AND brand = 'Apple')
这样才能准确地表达“价格大于100且类别为‘Electronics’或者品牌为‘Apple’”的条件。
综上所述,不带括号的 price > 100 AND category = 'Electronics' OR brand = 'Apple'
表达式的实际运算逻辑是先计算 price > 100
与 category = 'Electronics'
的逻辑与,然后将结果与 brand = 'Apple'
进行逻辑或。为了避免混淆和确保查询语句表达意图的准确性,建议在涉及多个逻辑运算符时使用括号来明确指定优先级。
结合聚合函数与逻辑运算符
聚合函数通常在 GROUP BY
子句之后使用,对分组后的数据进行统计计算。当需要基于聚合结果应用逻辑判断时,可以在 HAVING
子句中使用逻辑运算符,因为 WHERE
子句无法直接作用于聚合函数。
例如:
SELECT department, COUNT(*) AS employee_count
FROM employees
GROUP BY department
HAVING COUNT(*) > 10; -- 应用逻辑运算符过滤出员工数量超过10人的部门
在这个查询中,COUNT(*)
是聚合函数,计算每个部门的员工数量。然后在 HAVING
子句中使用 >
逻辑运算符和常量值10,筛选出员工数量大于10的部门结果。
总结来说,MySQL 中聚合函数与逻辑运算符的混合使用涉及到运算优先级、结合性规则以及在适当位置(如 WHERE
、HAVING
子句)应用逻辑判断。理解并正确运用这些规则有助于编写精确、高效的 SQL 查询。
实训:
Enter password: ****
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.44-log MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
mysql>
mysql>
mysql> create databse if not exists testDB;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'datab
se if not exists testDB' at line 1
mysql> create database if not exists testDB;
Query OK, 1 row affected (0.03 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| bms |
| db_com |
| db_test1 |
| lb_db |
| lb_db1 |
| mysql |
| performance_schema |
| sys |
| test1 |
| test3 |
| test5 |
| testdb |
+--------------------+
13 rows in set (0.02 sec)
mysql> use testdb
Database changed
mysql> select database();
+------------+
| database() |
+------------+
| testdb |
+------------+
1 row in set (0.00 sec)
mysql> create table user
-> (id int auto_increment primary key,name varchar(30) not null unique,sex v
archar(30),score float default 0);
Query OK, 0 rows affected (0.17 sec)
mysql> show full columns form user\G;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'form
user' at line 1
ERROR:
No query specified
mysql> show full columns from user\G;
*************************** 1. row ***************************
Field: id
Type: int(11)
Collation: NULL
Null: NO
Key: PRI
Default: NULL
Extra: auto_increment
Privileges: select,insert,update,references
Comment:
*************************** 2. row ***************************
Field: name
Type: varchar(30)
Collation: latin1_swedish_ci
Null: NO
Key: UNI
Default: NULL
Extra:
Privileges: select,insert,update,references
Comment:
*************************** 3. row ***************************
Field: sex
Type: varchar(30)
Collation: latin1_swedish_ci
Null: YES
Key:
Default: NULL
Extra:
Privileges: select,insert,update,references
Comment:
*************************** 4. row ***************************
Field: score
Type: float
Collation: NULL
Null: YES
Key:
Default: 0
Extra:
Privileges: select,insert,update,references
Comment:
4 rows in set (0.01 sec)
ERROR:
No query specified
mysql> insert into user (name,sex,score) values
-> ('小明','男',55),
-> ('小红','女',72),
-> ('小张','男',88),
-> ('张三','男',80),
-> ('李四','女',40),
-> ('李梅','女',60),
-> ('小美','男',99);
ERROR 1366 (HY000): Incorrect string value: '\xE5\xB0\x8F\xE6\x98\x8E' for colum
n 'name' at row 1
mysql> alter table user convert to character set utf8mb4;
Query OK, 0 rows affected (0.26 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> insert into user (name,sex,score) values
-> ('小明','男',55),
-> ('小红','女',72),
-> ('小张','男',88),
-> ('张三','男',80),
-> ('李四','女',40),
-> ('李梅','女',60),
-> ('小美','男',99);
Query OK, 7 rows affected (0.02 sec)
Records: 7 Duplicates: 0 Warnings: 0
mysql> select * from user;
+----+--------+------+-------+
| id | name | sex | score |
+----+--------+------+-------+
| 1 | 小明 | 男 | 55 |
| 2 | 小红 | 女 | 72 |
| 3 | 小张 | 男 | 88 |
| 4 | 张三 | 男 | 80 |
| 5 | 李四 | 女 | 40 |
| 6 | 李梅 | 女 | 60 |
| 7 | 小美 | 男 | 99 |
+----+--------+------+-------+
7 rows in set (0.00 sec)
mysql> select * from name like '%张%';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'like
'%张%'' at line 1
mysql> select * from user name like '%张%';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'like
'%张%'' at line 1
mysql> select * from user where name like '%张%';
+----+--------+------+-------+
| id | name | sex | score |
+----+--------+------+-------+
| 3 | 小张 | 男 | 88 |
| 4 | 张三 | 男 | 80 |
+----+--------+------+-------+
2 rows in set (0.04 sec)
mysql> select * from user where name like '%四%';
+----+--------+------+-------+
| id | name | sex | score |
+----+--------+------+-------+
| 5 | 李四 | 女 | 40 |
+----+--------+------+-------+
1 row in set (0.00 sec)
mysql> select score from user where name='张三';
+-------+
| score |
+-------+
| 80 |
+-------+
1 row in set (0.01 sec)
mysql> select * from user where id=1 or id=2;
+----+--------+------+-------+
| id | name | sex | score |
+----+--------+------+-------+
| 1 | 小明 | 男 | 55 |
| 2 | 小红 | 女 | 72 |
+----+--------+------+-------+
2 rows in set (0.01 sec)
mysql> select * from user where score between 80 and 90;
+----+--------+------+-------+
| id | name | sex | score |
+----+--------+------+-------+
| 3 | 小张 | 男 | 88 |
| 4 | 张三 | 男 | 80 |
+----+--------+------+-------+
2 rows in set (0.00 sec)
mysql> select * from user where score>90;
+----+--------+------+-------+
| id | name | sex | score |
+----+--------+------+-------+
| 7 | 小美 | 男 | 99 |
+----+--------+------+-------+
1 row in set (0.01 sec)
mysql> select id,name,sex,avg(score) from user;
ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1 of SELEC
T list contains nonaggregated column 'testdb.user.id'; this is incompatible with
sql_mode=only_full_group_by
mysql> select avg(score) from user;
+-------------------+
| avg(score) |
+-------------------+
| 70.57142857142857 |
+-------------------+
1 row in set (0.01 sec)
mysql>
MySQL高级查询
MySQL第四章节单表查询.pptx
https://www.alipan.com/s/3F31d12DNok
点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。