inner join on 加条件和where加条件_打开SQL复杂查询的钥匙:正确理解where、having和on的区别...

SQL查询,是数据库人用凌波微步都躲不过的一道槛。

非常凑巧,就在前几天,小编的一个朋友在面试时遇到一个SQL查询的问题,“请解释SQL中where与having的区别,最好举个例子”。他支吾了一句,“选择having一般是在无法用where的时候”。其实除了where和having,where和on也是面试官们经常喜欢问的问题。

那这三者究竟有什么区别呢,借此机会,小编就学习和整理了一些资料,分享给大家。

f9e9e2067b52b40783194a315bd7f676.png

放大镜在灰色背景上显示sql字

一、where和having

  • “where”是在结果返回之前起作用,where后面不能使用“聚合函数”;
  • “having”是在结果返回之后起作用,having后面可以使用“聚合函数”

常见的聚合函数如:求总和sum() ,求最大值 max() ,求最小值 min() ,求平均值avg()

通过下面的例子来说明:

食品表 food,表字段 name(名称)、price(价格)、category(种类)、number(数量)

1. where和having 都可以用的场景

如:查询价格大于50的食品和价格

221304a09ba9936247878109409fee51.png

说明:having是从前面筛选的字段再筛选,而where是从数据表中的字段直接进行的筛选的,select price已经筛选,所以此时where和having效果是一样的。

2.只可以用having,不可以用where情况

如:查询每种食品category 的价格平均值,获取平均价格大于200的食品

77a8379c68fe87a357902fb85c8fc1db.png

说明:这里只能用having,是因为where后面要跟的东西必须是表格里的字段,换成avg(price)也是错的,而having此时就有优势了,它是根据前文查询的内容来是筛选,不论在表中是否有该字段。

3.只可以用where,不可以用having的情况

如:查询价格大于100的食品和数量

54bf0f10bf5585e4b61546c29322912a.png

说明:这里不能用having的理由是,having是根据前文查询结果来筛选,前文并没有告诉它price是多少,所以报错。

二、where和on

数据库在连接两张表或多张表来返回记录时,都会生成一张临时表。在使用左连接left join 时,where和on有如下区别:

  • “where”是在临时表生成好后,再对临时表进行过滤。
  • “on”是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。
fa5957bf9c8f30964b98d8e00d3c727a.png

两条查询语句:

1、select * form A left join B on (A.id = B.id) where B.name='aa'2、select * form A left join B on (A.id = B.id and B.name='aa')

第一条的执行过程如下:

1210bf752978f16dce4885ef9df7a598.png

第二条的执行过程如下:

5dd3e7c7a5583116fed210f109339402.png

通过上面的例子可以看出,on子句不管on上的条件是否为真都会返回left或right表中的记录;where子句是在临时表生成好后,再对临时表进行过滤的条件,且这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。

最后

where、having、on 这三个都可以加条件的子句中,它们的执行顺序是 on > where > having。有时候如果这先后顺序不影响中间结果的话,那最终结果是相同的。

关于三者的查询速度,因为on是先把不符合条件的记录过滤后才进行统计,可以减少中间运算要处理的数据,所以按理说速度应该是最快的。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
select c.area_name,c.mon,c.count,ifnull(c1.count1,0),ifnull(c1.count1,0)/count * 100 from ( select a.area_name,MONTH(pb.wlpb_create_time) mon,count(pb.id) count from bc_company_info b inner join ( select b.id from wk_ledger_produce_gather g left join bc_company_info b on b.id =g.bci_id where g.wlpg_year =2022 group by b.id HAVING sum(g.wlpg_total_produce) >=30 UNION select b.id from wk_plan_info p left join wk_plan_danger d on d.wpi_id = p.id left join bc_company_info b on b.id = p.bci_id where p.wpi_year = 2022 group by b.id HAVING sum(d.wpd_this_produce) >30) b1 on b1.id = b.id left join wk_ledger_produce_bill pb on pb.bci_id = b.id left join sys_area a on a.id = b.bci_city where pb.wlpb_create_time >'2023-01-01 00:00:00' group by b.bci_city,MONTH(pb.wlpb_create_time) ) c left join ( select a.area_name,MONTH(pb.wlpb_create_time) mon,count(pb.id) count1 from bc_company_info b inner join ( select b.id from wk_ledger_produce_gather g left join bc_company_info b on b.id = g.bci_id where g.wlpg_year =2022 group by b.id HAVING sum(g.wlpg_total_produce) >=30 UNION select b.id from wk_plan_info p left join wk_plan_danger d on d.wpi_id = p.id left join bc_company_info b on b.id = p.bci_id where p.wpi_year = 2022 group by b.id HAVING sum(d.wpd_this_produce) >30) b1 on b1.id = b.id left join wk_ledger_produce_bill pb on pb.bci_id = b.id left join sys_area a on a.id = b.bci_city where pb.wldb_end_from != 1 and pb.wlpb_create_time >'2023-01-01 00:00:00' group by b.bci_city,MONTH(pb.wlpb_create_time)) c1 on c.area_name = c1.area_name and c.mon = c1.mon 这段SQL怎么优化
06-09

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值