MySQL查询语言之连接表

本文讲述了在SQL查询中遇到的问题,如何通过外连接处理不同表之间的数据,解决笛卡尔积现象,并使用左外连接和ifnull函数确保正确计算产品平均售价,即使某些产品没有销售记录也包含在结果中。
摘要由CSDN通过智能技术生成

刚好碰见了一个细节满满的外连接题目,拿过来分享一下

题目描述:

编写解决方案以查找每种产品的平均售价。average_price 应该 四舍五入到小数点后两位

返回结果表 无顺序要求

结果格式如下例所示。

题目分析:

很明显,输出的average_price是无法通过单一的表计算得到,所以一定会用到连接表。

我最开始写的代码为:

select 
Prices.product_id,
ifnull(round(sum(Prices.price*UnitsSold.units)/sum(UnitsSold.units),2),0) as average_price
from
Prices join UnitsSold on UnitsSold.product_id=Prices.product_id --内连接 
group by UnitsSold.product_id;

我本来以为Prices table中的product_id与UnitSold中的product_id是一一对应的关系,于是用了内连接,运行结果如下:

问题很大,答案全不对,于是我想到要看一看我连接的表到底长什么样子,于是我修改了代码,查看表的全部信息:

select 
*
from
Prices join UnitsSold on UnitsSold.product_id=Prices.product_id;

连接表中相同product_id居然有四条结果,出现了笛卡尔积现象,我觉得该连接表出现该现象不可避免,仔细分析题目, 我增加了对该表的筛选条件:between Prices.start_date and Prices.end_date,筛选出出售日期对应价格的时间段

select 
*
from
Prices join UnitsSold on UnitsSold.product_id=Prices.product_id
where (UnitsSold.purchase_date between Prices.start_date and Prices.end_date);

现在这个表看起来没问题了。那么就根据这个表筛选

# Write your MySQL query statement below
select 
Prices.product_id,
round(sum(Prices.price*UnitsSold.units)/sum(UnitsSold.units),2) as average_price
from
Prices join UnitsSold on UnitsSold.product_id=Prices.product_id
where UnitsSold.purchase_date between Prices.start_date and Prices.end_date
group by UnitsSold.product_id;

-- round(查询内容,2),保留两位小数
-- group by ,按照UnitsSold.product_id分组

测试案例通过,提交代码。

醒目的解答错误告诉我还有没考虑到的细节,于是我仔细分析错误案例2,得到以下错误原因

Price表中的product_id中有UnitsSold表中未出现过的id

解决办法:

将内连接改成左外连接,

将筛选条件改为where (UnitsSold.purchase_date between Prices.start_date and Prices.end_date) or UnitsSold.purchase_date is null

将查询内容改为ifnull(round(sum(Prices.price*UnitsSold.units)/sum(UnitsSold.units),2),0)

完整代码如下

# Write your MySQL query statement below
select 
Prices.product_id,
ifnull(round(sum(Prices.price*UnitsSold.units)/sum(UnitsSold.units),2),0) as average_price
from
Prices left join UnitsSold on UnitsSold.product_id=Prices.product_id
where (UnitsSold.purchase_date between Prices.start_date and Prices.end_date) or UnitsSold.purchase_date is null
group by UnitsSold.product_id;

--ifnull(查询内容,0):查询内容为null则输出0
-- 如果筛选内容不加or UnitsSold.purchase_date is null,则会剔除空行

 

通过!

  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值