MySQL表连接引入,DISTINCT去重【MySQL】

Java养成计划----学习打卡第六十七天

Java(打卡第六十七天)


MySQL数据库连接查询,distinct去重
> DBMS --> SQL ----> DB dbms是软件【数据库管理系统】,通过SQL 结构查询语言操作数据库database DB

distinct 查询结果去重

有的时候查询的结果有很多并且大量重复,这个时候就要使用distinct去重,使用的格式是将distinct加到去重字段前面 distinct different

SELECT DISTINCT col_name FROM table_name

这里演示一下

mysql> SELECT
    -> DISTINCT CountryCode
    -> FROM
    -> city
    -> WHERE
    -> ID <= 100;
+-------------+
| CountryCode |
+-------------+
| AFG         |
| NLD         |
| ANT         |
| ALB         |
| DZA         |
| ASM         |
| AND         |
| AGO         |
| AIA         |
| ATG         |
| ARE         |
| ARG         |
+-------------+
12 rows in set (0.01 sec)

这个关键字有几个需要注意的地方

  • 用distinct修饰的字段不能和普通的字段并列,会直接报错,因为数量不匹配
  • distinct可以直接修饰很多的字段,Mysql的处理方法是将需要修饰的字段连接在一起,以整体为规模来去重
mysql> SELECT
    -> DISTINCT Name,CountryCode
    -> FROM
    -> city
    -> WHERE
    -> ID <= 10;
+----------------+-------------+
| Name           | CountryCode |
+----------------+-------------+
| Kabul          | AFG         |
| Qandahar       | AFG         |
| Herat          | AFG         |
| Mazar-e-Sharif | AFG         |
| Amsterdam      | NLD         |
| Rotterdam      | NLD         |
| Haag           | NLD         |
| Utrecht        | NLD         |
| Eindhoven      | NLD         |
| Tilburg        | NLD         |
+----------------+-------------+
10 rows in set (0.00 sec)

比如这里就没有CONCAT(Name,CountryCode)就没有重复的内容,所以就还是10个

  • COUNT 可以和DISTINCT一起使用,因为SELECT后面可以接分组函数,并且统计的就是去重后的所有数据
mysql> SELECT
    -> COUNT(DISTINCT(CountryCode))
    -> FROM
    -> city
    -> WHERE
    -> ID <= 100;
+------------------------------+
| COUNT(DISTINCT(CountryCode)) |
+------------------------------+
|                           12 |
+------------------------------+
1 row in set (0.01 sec)

和上面的数据是对应的

连接查询

从一张表中单独查询称为单表查询,

从多张表中联合起来查询数据,比如从a表中取name,从b表中取location,这种跨表查询,多张表联合查询数据,被称为连接查询

这里就以world数据库为例,三张表city,country,countrylanguage是有关系的,比如查询一个城市所处的大陆,就要同时借助city表和country表

连接查询的分类

根据语法的年代分类

  • SQL92 : 1992年出现的语法
  • SQL99: 1999年出现的语法

根据表连接的方式

  • 内连接

    • 等值连接
    • 非等值连接
    • 自连接
  • 外连接

    • 左外连接(左连接)
    • 右外连接(右连接)
  • 全连接

这里来一个问题,当两张表的连接没有任何的限制,会发生什么事情

这里简单看一下这里的实验数据

+------+-------------+--------------+---------------+---------------+--------------+
| id   | fruits_name | fruits_price | fruits_origin | fruits_remark | fruits_bonus |
+------+-------------+--------------+---------------+---------------+--------------+
| 1001 | 葡萄        |          3.7 | 山东          | 红香妃        | NULL         |
| 1002 | 苹果        |          2.8 | 山东          | 红富士        | NULL         |
| 1003 | 香蕉        |            6 | 海南          | 小芭蕉        | NULL         |
+------+-------------+--------------+---------------+---------------+--------------+
3 rows in set (0.01 sec)

mysql> SELECT
    -> *
    -> FROM
    -> culture;
+----------+----------+
| location | language |
+----------+----------+
| 四川     | 四川话   |
| 山东     | 山东话   |
| 海南     | 海南话   |
+----------+----------+
3 rows in set (0.00 sec)

先操作着两张数据少的表,再操作world库,这里比如 可以匹配每种水果产地的方言

SELECT
col_name1,col_name2
FROM
table_name1,table_name2;

这里col_name1是表table_name1中的,col_name2在table_name2中

mysql> SELECT
    -> fruits_name,language
    -> FROM
    -> fruits,culture;
+-------------+----------+
| fruits_name | language |
+-------------+----------+
| 香蕉        | 四川话   |
| 苹果        | 四川话   |
| 葡萄        | 四川话   |
| 香蕉        | 山东话   |
| 苹果        | 山东话   |
| 葡萄        | 山东话   |
| 香蕉        | 海南话   |
| 苹果        | 海南话   |
| 葡萄        | 海南话   |
+-------------+----------+
9 rows in set (0.00 sec)

数据库中,是将第一张表中的每一行数据和第二张表的每一行数据匹配,所以这里如果不加限制,输出的是m*n行数据,也就是9行,并且没有达到搜索

笛卡尔积现象

当两张表进行连接查询时,没有任何条件限制,最终的查询结果条数,时两张表条数的乘积,这种现象就是笛卡尔积现象

所以要避免笛卡尔积现象,那么就要加上限制,比如这里就是要水果的产地和location相等的时候才匹配

//可以使用.来引用
basename.tablename.colname
//之前演示过不使用USE连接数据库,直接使用basename.tablename来查表

SELECT 
col_name1,col_name2
FROM
table_name2,table_name2
WHERE
table_name1.col = table_name2.col

这也就是相等的时候才匹配

mysql> SELECT
    -> fruits_name,language
    -> FROM
    -> fruits,culture
    -> WHERE
    -> fruits.fruits_origin = culture.location;
+-------------+----------+
| fruits_name | language |
+-------------+----------+
| 葡萄        | 山东话   |
| 苹果        | 山东话   |
| 香蕉        | 海南话   |
+-------------+----------+
3 rows in set (0.00 sec)
  • 注意:最终的查询结果虽然减少了,但是匹配次数还是没有减少,匹配次数还是两张表的行数之积

给表起别名减少匹配次数

不是起了别名就可以减少次数了,起别名之后表名可以很简单,所有的字段都加上限制,包括SELECT后面的字段

起别名的方式和字段起别名的方式是相同的

mysql> SELECT
    -> f.fruits_name '水果名称',l.language AS '地方方言'
    -> FROM
    -> fruits f,culture l
    -> WHERE
    -> f.fruits_origin = l.location;
+----------+----------+
| 水果名称 | 地方方言 |
+----------+----------+
| 葡萄     | 山东话   |
| 苹果     | 山东话   |
| 香蕉     | 海南话   |
+----------+----------+
3 rows in set (0.01 sec)

因为FROM是最先执行的,所以FROM之后起的别名后面都是可以用的,而这里SELECT是最后执行的,只是显示的时候才显示别名

这里给两张表都起了别名,并且就算不加别名,这里的f.fruits_name不会带入的,还是fruits_name

需要注意的是,这里是使用的SQL92语言

mysql> SELECT
    -> f.fruits_name,c.language
    -> FROM
    -> fruits f,culture c
    -> WHERE
    -> f.fruits_origin =  c.location;
+-------------+----------+
| fruits_name | language |
+-------------+----------+
| 葡萄        | 山东话   |
| 苹果        | 山东话   |
| 香蕉        | 海南话   |
+-------------+----------+
3 rows in set (0.04 sec)

字段的操作只会带入字段的操作过程,.引用并没有修改字段,不会带入字段名

通过笛卡尔积现象,表的连接次数越多效率越低,尽量避免表的连接次数,因为数据库的底层操作就是逐条匹配数据表的数据,匹配次数就是笛卡尔积,所以要对表使用别名来减少表的连接次数

内连接— 等值查询

内连接,就是INNER JOIN ON ,等值查询就是说表连接的条件是等量关系,比如这里就是f.fruits_origin = c.location时才查询

上面就是使用的是SQL92语法,这个语法的问题就在于结构不够清晰,因为表连接条件就是使用的WHERE来写的,但是查询的时候是需要进行其他过滤的,这样表的连接条件和普通的过滤条件就会使用AND连接在一起,结果不清晰

所以SQL99就改变了结构,特点就是连接条件是独立的,如果需要进一步的过滤,直接加WHERE再进行过滤

使用关键字JOIN 来表示两张表,ON来表达连接条件

所以上面的查询语句

mysql> SELECT
    -> f.fruits_name,c.language
    -> FROM
    -> fruits f  
    -> JOIN        //连接另外一张表
    -> culture c
    -> ON          //连接条件
    -> f.fruits_origin = c.location;

所以这个表连接过程和条件查询时分开的,就是讲两个过程分离,不能糅杂在一起

基本的格式就是

SELECT
……
FROM
table_name1
JOIN
table_name2  //需要连接table_name2表
ON
……连接条件
WHERE
……筛选条件

执行顺序就是进行FROM,之后执行JOIN语句,之后执行ON,连接条件,之后再执行WHERE……【之前的单表查询顺序】

这里其实就是内连接,省略了INNER,INNNER JOIN

mysql> SELECT
    -> f.fruits_name,c.language
    -> FROM
    -> fruits f
    -> INNER JOIN
    -> culture c
    -> ON
    -> f.fruits_origin = c.location;

也就是默认情况下,就是内连接【带着INNER,可读性更好】

接下来的非等值连接还有内外连接的阐释明天继续,今天时间有点紧~🌳

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值