mysql SQL 集锦:join_and 和 多次join同一张表的处理 和 group_concat 和 find_in_set

Join 和 and

在使用left join时,on and和on where条件的区别如下:
1、on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。
2、where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉,on后的条件用来生成左右表关联的临时表,where后的条件对临时表中的记录进行过滤。

表结构
	SQL> create table A (id int, type int);
	SQL> select * from A;
	        ID       TYPE
	---------- ----------
	         1          1
	         2          1
	         3          2
	 
	SQL> create table B(id int ,class int);
	SQL> select * from B;
	 
	        ID      CLASS
	---------- ----------
	         1          1
	         2          2

不使用条件
	SQL> select * from A left join B on A.id = b.id;
	 
	        ID       TYPE         ID      CLASS
	---------- ---------- ---------- ----------
	         1          1          1          1
	         2          1          2          2
	         3          2
	

使用条件where
	SQL> select * from A left join B on A.id = B.id where A.type = 1;
	 
	        ID       TYPE         ID      CLASS
	---------- ---------- ---------- ----------
	         1          1          1          1
	         2          1          2          2
	根据上面那段话的解释,where字句是在生成临时表以后再进行过滤的,也就是可以理解为就是一个左连接:
	select * from A left join B on A.id = B.id,然后加上where A.type = 1对临时表进行过滤,除掉A.type不为1的数据。

 

使用and 
	SQL> select * from A left join B on A.id = B.id and A.type = 1;  (这需要操作确认)
	 
	        ID       TYPE         ID      CLASS
	---------- ---------- ---------- ----------
	         1          1          1          1
	         2          1          2          2
	         3          2
	因为左连接不管on and语句是否为真都必须返回左表所有的记录,所以and A.type=1;没有起到任何作用。

	SQL> select * from A left join B on A.id = B.id and B.class = 1;
	 
	        ID       TYPE         ID      CLASS
	---------- ---------- ---------- ----------
	         1          1          1          1
	         3          2
	         2          1	
	根据上面那段话的解释:on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。
	显然左连接再加上新的条件:B.class = 1筛选掉第二行记录,结果正确。

使用 where:
	SQL> select * from A left join B on A.id = B.id where B.class = 1;
	 
	        ID       TYPE         ID      CLASS
	---------- ---------- ---------- ----------
	         1          1          1          1

	where是生成临时表以后再进行过滤,对左右表都进行筛选。
	如果是and,先不管过滤规则,先把左边表数据全部返回,然户过滤规则只对右表产生过滤。

再来看看内连接inner join  on and和 on where的区别:
在使用inner join时,不管是对左表还是右表进行筛选,on and和on where都会对生成的临时表左右两边同时进行过滤。

表结构 
	SQL> select * from A;
	 
	        ID       TYPE
	---------- ----------
	         1          2
	         2          1
	         3          2
	 
	SQL> select * from B;
	 
	        ID      CLASS
	---------- ----------
	         1          1
	         2          2

inner join 的特性就是只返回有匹配的
	SQL> select * from A inner join B on A.id = B.id;
	 
	        ID       TYPE         ID      CLASS
	---------- ---------- ---------- ----------
	         1          2          1          1
	         2          1          2          2
	SQL>
	SQL> select * from A inner join B on A.id = B.id where A.type = 1;
	 
	        ID       TYPE         ID      CLASS
	---------- ---------- ---------- ----------
	         2          1          2          2
	SQL> 
	SQL> select * from A inner join B on A.id = B.id and B.class = 1;
	 
	        ID       TYPE         ID      CLASS
	---------- ---------- ---------- ----------
	         1          2          1          1
	SQL>
	SQL> select * from A inner join B on A.id = B.id where B.class = 1;
	 
	        ID       TYPE         ID      CLASS
	---------- ---------- ---------- ----------
	         1          2          1          1
	
	发现会对左右两边同时过滤。

多次join同一张表的处理: join and or

select * from (
select nod.*, concat_ws(",",vi.vip, vi2.vip) as vip, vi.relation_id as aaa from node nod
left join cluster clu on clu.name = nod.cluster_name  and clu.owner = "sulijun6"
left join virtual_ip vi on nod.uniq_id = vi.relation_id and nod.role in ("master", "slave")
left join virtual_ip vi2 on nod.group_id = vi2.relation_id and nod.role = "roleless"
) as aa



select my_db.db_name, my_db.description, 
node.ip as ip, node.port as port, node.`role` as role, 
app.app_name_en, app.app_name_cn, app.owner, 
group_concat(distinct(account.hosts)) as app_hosts
from my_db
left join app on app.cluster_name = my_db.cluster_name 
left join account on account.cluster_uniq_id = my_db.cluster_uniq_id 
left join ha_group hg on hg.cluster_uniq_id = my_db.cluster_uniq_id 
left join proxy_group pg on pg.cluster_uniq_id = my_db.cluster_uniq_id 
left join node on (node.group_id = hg.uniq_id and node.`role` in ('master', 'slave')) or (node.group_id = pg.uniq_id and node.`role` = 'roleless')
group by app.app_name_en, my_db.db_name, node.ip

group_concat: 没有 group by 也可以使用

mysql> select * from student;
+----+----------+--------+---------+----------------------------+----------------------------+------------+
| id | name     | gender | address | create_date                | update_date                | country_id |
+----+----------+--------+---------+----------------------------+----------------------------+------------+
|  2 | fromjdbc |      2 | HeNan   | 2020-12-25 15:13:18.000000 | 2020-12-25 15:13:18.000000 |          1 |
|  3 | Michael  |      1 | BeiJing | 2020-12-25 15:13:55.000000 | 2020-12-25 17:07:56.024261 |          2 |
|  4 | cpx      |      1 | BeiJing | 2020-12-30 19:46:41.000000 | 2020-12-30 19:46:41.000000 |          2 |
|  5 | cpxx     |      1 | BeiJing | 2020-12-30 19:46:50.000000 | 2022-06-07 10:30:33.432000 |          1 |
|  6 | aa       |      2 | aaa     | 2022-10-26 19:06:26.000000 | 2022-10-26 19:06:26.000000 |          1 |
|  8 | jdbc1    |      1 | SH      | 2022-10-26 08:18:29.438000 | 2022-10-26 08:18:29.438000 |          1 |
|  9 | 11111    |      1 | SH      | 2022-10-26 08:21:22.657000 | 2022-10-26 08:21:23.255000 |          1 |
| 10 | jdbc1    |      1 | SH      | 2022-10-26 08:23:51.336000 | 2022-10-26 08:23:51.860000 |          1 |
| 11 | jdbc0    |      1 | SH      | 2022-10-26 08:25:48.981000 | 2022-10-26 08:25:48.981000 |          1 |
| 12 | jdbc1    |      1 | SH      | 2022-10-26 08:25:48.981000 | 2022-10-26 08:25:48.981000 |          1 |
+----+----------+--------+---------+----------------------------+----------------------------+------------+
10 rows in set (0.00 sec)

mysql>
mysql> select group_concat(name  SEPARATOR ',') from student;
+------------------------------------------------------------+
| group_concat(name  SEPARATOR ',')                          |
+------------------------------------------------------------+
| fromjdbc,Michael,cpx,cpxx,aa,jdbc1,11111,jdbc1,jdbc0,jdbc1 |
+------------------------------------------------------------+
1 row in set (0.00 sec)

mysql>

find_in_set

FIND_IN_SET(str,strlist),该函数的作用是查询字段(strlist) 中是否包含(str)的结果,返回结果为 null或记录 。

SELECT FIND_IN_SET('b', 'a,b,c,d');
// 结果:2.  因为 b 在strlist集合中2的位置, a是位置1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值