SQL DQL语句
查询数据 SELECT
DQL是数据库查询语言,主要就是通过SELECT关键字来从数据库中查询指定规则的数据。
语法格式:
SELECT
需要查询的列名字
FROM
表名称
WHRER
查询条件
说明:
1、如果需要查询所有的列,SELECT的参数指定为 * ,如果查询的列名有多个,使用逗号隔开
2、如果没有使用 where 指定查询条件,默认就是查询表中所有数据的信息
1、排序规则 ORDER BY
默认情况下,使用select查询出来的结果是按照它在表中出现的顺序显示,如果需要将查询出来的数据进行排序,可以使用 ORDER BY 关键字来指定。 ORDER BY 指定的参数就是排序的依据。
例如:
SELECT
Name
FROM
Employees
ORDER BY
Salary;
ORDER BY特点:
1、ORDER BY关键字只能位于一条SQL语句的最后面,它的后面不能在有SQL关键字
2、使用 ORDER BY 指定的列名来进行排序时,即使这个列在最终的查询结果中没有显示出来也可以
3、如果指定多个列名进行排序时,要用逗号进行隔开
4、ORDER BY的默认排序规则事升序(Ascending即ASC),如果想要以降序(Descending即DESC)排序,需要在 ORDER BY 子句后明确指定 DESC 关键字
2、指定过滤条件 WHERE
如果需要查询符合特定条件的行,就需要使用WHRER关键字来指定过滤条件。where支持很多操作符号,最常用的就是 = 号了,还有其它一些操作符可以使用。
单个值检查:
= > <> >= IS NULL
IS NULL # 判断是否为NULL值
# <> 表示的是不等于
多值检查:
BETWEEN:在指定的两个值之间
where说明:
1、whrer 指定的参数就是进行过滤的条件,列名 操作符 值
, 如果值是字符串的话需要用引号括起来,数值不用加引号。
2、如果过滤条件有多个,可以用OR或者AND关键字来进行连接,AND的话输出的是条件都满足的行会输出,OR的话是满足其一即可。
3、还有一个类西域OR的关键字IN,用于指定一个范围检查某列的值是否在这个范围内。使用IN操作符时,小括号用于封装一系列的值,以便进行比较操作
4、还可以指定通配符进行过滤,这个时候需要使用like关键字,常用的通配符有两个。%表示任何字符出现任意次。下划线(\_)表示它只匹配单个字符数
例如:
SELECT * FROM Students where id IN (1,2,3,4,5)
3、五个聚合函数
聚合函数是通过执行一系列值上的计算,并返回单个值的函数。所以聚合函数的特点就是最终结果返回一个值。
标准的SQL提供了5个聚合函数:
(1)count();输出满足特定条件的行数字,如果参数为 * 表示通过真个数据表有多少行。
mysql> select count(*) from tb_locationinfo_20231112;
+----------+
| count(*) |
+----------+
| 111 |
+----------+
1 row in set (0.19 sec)
# 传递的参数是一个列名字,则该列中有值(即非 NULL 值)的行会被计数。
mysql> select count(card_id) from tb_locationinfo_20231112;
+----------------+
| count(card_id) |
+----------------+
| 111 |
+----------------+
1 row in set (0.00 sec)
(2)MAX():计算指定列中的最大值。传递的参数是一个列名字
mysql> select MAX(card_id) from tb_locationinfo_20231112;
+--------------+
| MAX(card_id) |
+--------------+
| 313556 |
+--------------+
1 row in set (0.00 sec)
(3)MIN():计算指定列中的最小值。传递的参数是一个列名字
(4)SUM():计算指定列的总和
mysql> select SUM(card_id) from tb_locationinfo_20231112;
+--------------+
| SUM(card_id) |
+--------------+
| 2432755 |
+--------------+
1 row in set (0.00 sec)
说明:
SUM 函数设计用于对数值数据(如整数、浮点数等)进行操作,而对于字符、字符串或其他非数值数据类型,它不知道如何进行合适的求和操作。所以对非数值列(如字符或文本列)进行求和时,这通常会导致错误或异常。
(5)AVG():计算某列数值的平均值,和SUM一样是对数值类型数据进行操作。
mysql> select AVG(card_id) from tb_locationinfo_20231112;
+--------------+
| AVG(card_id) |
+--------------+
| 21916.7117 |
+--------------+
1 row in set (0.02 sec)
4、指定别名 AS
为了提高可读性和简化查询语句,可以使用 AS 关键子来指定别名,可以为列、表或者聚合函数指定别名。
5、数据分组 GROUP BY
一般使用聚合函数的时候,都需要姜输出结果进行分组。要实现分组功能就需要使用 GROUP BY 关键字了,使用这个关键字的时候需要指定分组的列。
GROUP BY有一个特点,就是在输出的列中,除了是聚合函数外,只有GROUP BY 关键字指定的列才可以直接出现在 SELECT 语句的列列表中。
错误示范:
group by 关键字指定的分组依据是 power 列,但是select 却列出了所有列。这是不对的
select * from tb_card group by power ;
正确示范:
select power, count(*) from tb_card group by power;
单独使用数据分组:
主要就是用来去重的吧,将指定字符的重复数据只输出一次。效果和使用 DISTINCT 关键字的效果相同
例如:
mysql> select ip from tb_log group by ip;
+----------------+
| ip |
+----------------+
| 192.168.14.99 |
| 192.168.14.159 |
| 192.168.12.170 |
| 192.168.13.79 |
| 192.168.15.177 |
| 192.168.12.177 |
| 192.168.5.202 |
| 192.168.13.74 |
| 192.168.13.84 |
| 192.168.13.153 |
| 192.168.13.166 |
| 192.168.17.1 |
| 192.168.14.181 |
+----------------+
13 rows in set (0.00 sec)
# 使用 distinct关键字也能去重
mysql> select DISTINCT ip from tb_log group by ip;
结合聚合函数使用:
分组结合聚合函数使用就可以实现一些更高级的数据分析功能了。
例如:
mysql> select ip, count(*) from tb_log group by ip;
+----------------+----------+
| ip | count(*) |
+----------------+----------+
| 192.168.14.99 | 20 |
| 192.168.14.159 | 27 |
| 192.168.12.170 | 2 |
| 192.168.13.79 | 1 |
| 192.168.15.177 | 1 |
| 192.168.12.177 | 1 |
| 192.168.5.202 | 1 |
| 192.168.13.74 | 5 |
| 192.168.13.84 | 116 |
| 192.168.13.153 | 3 |
| 192.168.13.166 | 1 |
| 192.168.17.1 | 1 |
| 192.168.14.181 | 10 |
+----------------+----------+
13 rows in set (0.00 sec)
当 COUNT(*) 与 GROUP BY 一起使用时,查询的过程是这样的:
1、首先,SQL 会根据 GROUP BY 子句中指定的列对数据进行分组。意味着所有具有相同 ip 值的行会被归为同一组。
2、接着,对于每个这样的分组,COUNT(*) 聚合函数会计算该分组内的行数。
3、最后,查询的结果将列出每个唯一的 ip 地址及其在表中出现的行数。
所以,如果没有指定分组,count(*)表示获取整个表的行数,如果指定了分组,表示的是每个分组中的行数。
所以由此我们可知,当聚合函数(如 SUM, AVG, MAX, MIN, COUNT 等)与 GROUP BY 子句一起使用时,聚合函数的操作范围变为 GROUP BY 指定的每个分组,而不是整个表。这意味着聚合函数将对每个分组中的数据进行独立的计算。
6、条件过滤 HAVING
在某些时候,使用分组结合聚合函数将数据输出后,可能还需要对输出的内容进行一定的过滤。
例如:
mysql> select ip, count(*) as count from tb_log group by ip;
+----------------+-------+
| ip | count |
+----------------+-------+
| 192.168.14.99 | 20 |
| 192.168.14.159 | 27 |
| 192.168.12.170 | 2 |
| 192.168.13.79 | 1 |
| 192.168.15.177 | 1 |
| 192.168.12.177 | 1 |
| 192.168.5.202 | 1 |
| 192.168.13.74 | 8 |
| 192.168.13.84 | 116 |
| 192.168.13.153 | 3 |
| 192.168.13.166 | 1 |
| 192.168.17.1 | 1 |
| 192.168.14.181 | 10 |
+----------------+-------+
13 rows in set (0.00 sec)
如果需要过滤数量大于10的ip地址,使用where指定过滤条件的话会提示异常。
mysql> select ip, count(*) as count from tb_log group by ip where count > 10;
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 'where count > 10' at line 1
因为 WHERE 的条件必须针对原始数据表中实际存在的列。而且根据SQL语法规定,where只能过滤分组之前的数据,如果要过滤分组之后的数据,SQL 给了一个having关键字,这个关键字指定的选项不一定在表中真实存在,例如count就是聚合函数count(*)的别名。
所以正确的用法是:
mysql> SELECT ip, COUNT(*) AS count FROM tb_log GROUP BY ip HAVING count > 10;
+----------------+-------+
| ip | count |
+----------------+-------+
| 192.168.14.99 | 20 |
| 192.168.14.159 | 27 |
| 192.168.13.84 | 116 |
+----------------+-------+
3 rows in set (0.00 sec)
7、子查询
所谓的子查询就是将一个select语句嵌套在另外一个语句(SELECT、INSERT、UPDATE 或 DELETE)里面。
子查询出现位置:
子查询可以出现在多个地方,包括 SELECT 子句(作为列的一部分)、FROM 子句(作为数据源)、WHERE 子句(作为条件的一部分)等。
例如:
select 子查询语句 FROM tb_name
select 列名 FROM 子查询语句
select 列名 FROM tb_name where 子查询语句
8、联结表 join
联结表就是表中表之间的共同字段来将这些表进行结合,从而可以从多个表中查询相关数据。
内联结 iner join
内联结又叫做等值联结,是基于两个表中指定列的值相等来联结数据,只有当这两个表中的指定列值匹配时,相关的记录才会出现在查询结果中。
语法格式:
select 需要显示的列名
FROM table1,table2
WHERE
联结条件
例如:
SELECT vend_name, prod_name, prod_price FROM Vendors, Products WHERE Vendors.vend_id = Products.vend_id;
这种方式是通过 FROM 来指定联结的表,通过 WHERE指定联结两个表的条件。这种SQL风格早期的时候使用很多,但是存在一个问题就是在处理更多的表和更复杂的操作时候,不好维护。所以后面搞了个SQL语法叫作显式内联结。
显式内联结语法:
select
列名
FROM
A_table inner join B_table
ON
联结条件
这种通过 inner join来列出进行联结的两个表,通过 ON来指定联结条件,在处理多表联结和复杂查询时更加清晰,易于维护
例如:联结两个表
SELECT
vend_name, prod_name, prod_price
FROM
Vendors
INNER JOIN
Products
ON
Vendors.vend_id = Products.vend_id;
使用场景: 需要从两个或更多相关表中结合,输出对应信息
外联结 out join
和内联结不同的是,外联结会会包含没有匹配项的行根据包含未匹配行的表的不同,又分为左联结(left join),右联结(right join)和全联结(full jion)。
-
左联结:返回左表(LEFT JOIN 左侧的表)的所有记录,以及右表中与左表匹配的记录。如果右表中没有匹配项,则相应的部分会显示为 NULL
-
右联结:返回右表(RIGHT JOIN 右侧的表)的所有记录,以及左表中与右表匹配的记录。如果左表中没有匹配项,则相应的部分会显示为 NULL
-
全联结:返回左表和右表中的所有记录。如果一侧的表中没有匹配项,那么另一侧的相应部分将显示为 NULL
语法格式:
和内联结不同的是,使用隐式方法来实现外联结是不大可能实现的,官方只提供了显示的SQL语法规则。
# 左联结
SELECT 列名
A LEFT JOIN B
ON 联结条件
# 右联结
SELECT 列名
A RIGHT JOIN B
ON 联结条件
# 全联结
SELECT 列名
A FULL JOIN B
ON 联结条件
例如:
SELECT
tb_person.name as '姓名',
tb_branch.branch_name as '班组',
FROM_UNIXTIME(down_time) as '进入时间',
FROM_UNIXTIME(up_time ) as '离开时间',
CONVERT(stay_time/3600,DECIMAL(4, 1)) as '进洞时长'
FROM
tb_up_down_pit_record
LEFT JOIN
tb_person ON tb_up_down_pit_record.uuid =tb_person.uuid
LEFT JOIN
tb_branch ON tb_person.branch_id =tb_person.branch_id
ORDER BY `update_time` DESC
9、联合查询 UNION
UNION 是一个操作符,作用就是将多个SELECT语句的输出组合在一起,并且如果两个不同的 SELECT 语句产生了一些相同的行,UNION 会确保这些重复的行在最终结果集中只出现一次。
基本语法:
SELECT XXXX
UNION
SELECT XXXX;
UNION操作符特点:
1、如果不想把重复的行消除,使用 UNION ALL,它不会检查重复项
2、要使用 UNION 操作,需要满足以下两个条件:即SELECT 语句必须拥有相同数量的列和对应的列需要具有兼容的数据类型。
使用场景:
1、从不同的表中合并结构相似的数据
2、在某些情况下,UNION 可以作为连接(JOIN)多个表的一个更简单或更直观的替代方法,尤其是当涉及的表结构不便于直接连接时