MySQL派生表联表查询实战过程


Posted in MySQL onMarch 20, 2022

前情提要:

公司运营的一个商城系统,忽然发现订单提现功能有问题,有大量的商户体现金额和订单金额不一致。于是产生了需求,需要把提现表和供应商表作为一个结果集,连接上订单表中的订单金额,通过计算订单表的金额和体现表商户提现的金额进行比对,查看商户是多提现了还是少提现了。

下面记录我的查询过程。

查询过程:

刚开始,第一步我以提现表为主表,查询出来相关结果。MySQL语句如下

SELECT  count(ysw.supply_id) AS '提现次数',ysw.user_id AS '供应商对应的用户ID', ysw.supply_id  AS '供应商ID' ,SUM(ysw.money)  AS '供应商提现总金额',
case ysw.pay_type when 10 then '微信' when 20 then '支付宝' else '银行卡' end as '支付方式' ,
ys.supply_name AS '供应商名称',ys.money AS '供应商余额',ys.freez_money AS '供应商冻结金额(已提现金额)'
FROM yoshop_supply_withdraw AS ysw LEFT JOIN yoshop_supply AS ys ON ysw.supply_id = ys.supply_id
WHERE ysw.create_time < 1647446400 AND ysw.apply_status IN (10,20,40) GROUP BY ysw.supply_id
ORDER BY SUM(ysw.money) DESC ;

查询结果如图是正常的:

MySQL派生表联表查询实战过程

接下来,我在左链接上订单表的数据,又添加一个了left join,金额相关数据发生了变化严重不一致,而且查询时间明显延长,MySQL语句如下

SELECT  count(ysw.supply_id) AS '提现次数',ysw.user_id AS '供应商对应的用户ID', ysw.supply_id  AS '供应商ID' ,SUM(ysw.money)  AS '供应商提现总金额',
case ysw.pay_type when 10 then '微信' when 20 then '支付宝' else '银行卡' end as '支付方式' ,
ys.supply_name AS '供应商名称',ys.money AS '供应商余额',ys.freez_money AS '供应商冻结金额(已提现金额)',SUM(yo.pay_price)

FROM yoshop_supply_withdraw AS ysw LEFT JOIN yoshop_supply AS ys ON ysw.supply_id = ys.supply_id
LEFT JOIN yoshop_order AS yo ON yo.supply_ids =ysw.supply_id 

WHERE ysw.create_time < 1647446400 AND ysw.apply_status IN (10,20,40) GROUP BY ysw.supply_id
ORDER BY SUM(ysw.money) DESC ;

查询结果对比图如下:

MySQL派生表联表查询实战过程

经过实践,我想直接通过左连接查询到提现表金额和订单表金额是行不通的。通过网上查资料,以及在技术群里请教,

优化了思路: 把提现的统计好,把订单的统计好, 最后两个结果集再根据供应商id做个链接

接下来就是,三步走了, 第一步:把提现的统计好,上面第一次尝试的第一步就是了, 第二步:把订单表的数据统计好。由于使用系统的原因,我直接使用的订单商品表计算的订单总金额,这一步也是分三步走的,我直接上代码:

1.查询yoshop_order所有进行中,已完成的 订单id(order_id);
	SELECT order_id FROM yoshop_order WHERE order_status IN (10,30);
	
2.查询没有退款的订单ID
	SELECT order_id FROM yoshop_order WHERE order_status IN (10,30) AND order_id NOT IN ( SELECT order_id FROM yoshop_order_refund);
	
3.查询订单商品表中 所有的订单金额

SELECT  supply_id  AS '供应商ID' , SUM(total_pay_price)  AS '供应商订单总金额' FROM yoshop_order_goods WHERE  create_time < 1647446400 AND order_pay_status = 0  AND  order_id IN(SELECT order_id FROM yoshop_order WHERE order_status IN (10,30) AND order_id NOT IN ( SELECT order_id FROM yoshop_order_refund)	 )  GROUP BY supply_id 
ORDER BY SUM(total_pay_price) DESC ;

接下来就是进行把第一步和第二步的查询结果当作派生表,进行左连接查询。我在这一步耗费的时间和精力最多。如果你能认真看完,相信一定会有收货。我在这里把我错误的过程也进行了记录 第一次错误拼接:

SELECT * FROM  (
	SELECT  count(ysw.supply_id) AS '提现次数',ysw.user_id AS '供应商对应的用户ID', ysw.supply_id  AS 'supply_id' ,SUM(ysw.money)  AS '供应商提现总金额',
	case ysw.pay_type when 10 then '微信' when 20 then '支付宝' else '银行卡' end as '支付方式' ,
	ys.supply_name AS '供应商名称',ys.money AS '供应商余额',ys.freez_money AS '供应商冻结金额(已提现金额)'
	FROM yoshop_supply_withdraw AS ysw LEFT JOIN yoshop_supply AS ys ON ysw.supply_id = ys.supply_id
	WHERE ysw.create_time < 1647446400 AND ysw.apply_status IN (10,20,40) GROUP BY ysw.supply_id
	ORDER BY SUM(ysw.money) DESC ) AS t1 
union all    // left join ,这里是注释记得删除

SELECT * FROM   --  这里是错误的不应该在查询
		(SELECT  supply_id  AS 'supply_id' , SUM(total_pay_price)  AS total_pay_price FROM yoshop_order_goods WHERE  create_time < 1647446400 AND order_pay_status = 0  AND  order_id IN(
	SELECT order_id FROM yoshop_order WHERE order_status IN (10,30) AND order_id NOT IN (
	SELECT order_id FROM yoshop_order_refund)	 )  GROUP BY supply_id 
ORDER BY SUM(total_pay_price) DESC ) AS t2
								
ON t1.suppply_id = t2.suppply_id

通过这一次试错,明显看出我把left join 和 union all 的含义记错了,并且在拼接的时候重复使用了select * from 。虽然是试错了,但也是有收货的,接下来进行了第二次错误的拼接:

SELECT t1.提现次数 ,t1.供应商对应的用户ID ,t1.supply_id, t1.支付方式 ,t1.供应商名称,t1.供应商余额, t1.供应商冻结金额(已提现金额), t2.total_pay_price FROM  (
SELECT  count(ysw.supply_id) AS '提现次数',ysw.user_id AS '供应商对应的用户ID', ysw.supply_id  AS supply_id ,SUM(ysw.money)  AS '供应商提现总金额',
case ysw.pay_type when 10 then '微信' when 20 then '支付宝' else '银行卡' end as '支付方式' ,
	ys.supply_name AS '供应商名称',ys.money AS '供应商余额',ys.freez_money AS '供应商冻结金额(已提现金额)'
	FROM yoshop_supply_withdraw AS ysw LEFT JOIN yoshop_supply AS ys ON ysw.supply_id = ys.supply_id
	WHERE ysw.create_time < 1647446400 AND ysw.apply_status IN (10,20,40) GROUP BY ysw.supply_id
	ORDER BY SUM(ysw.money) DESC ) AS t1 
        
 LEFT JOIN
		
(SELECT  supply_id  AS supply_id , SUM(total_pay_price)  AS total_pay_price FROM 
yoshop_order_goods WHERE  create_time < 1647446400 AND order_pay_status = 0  
AND  order_id IN(
SELECT order_id FROM yoshop_order WHERE order_status IN (10,30) 
AND order_id NOT IN (
SELECT order_id FROM yoshop_order_refund)	 )  
GROUP BY supply_id 
ORDER BY SUM(total_pay_price) DESC ) AS t2						
ON t1.suppply_id = t2.suppply_id

通过这两次错误的尝试,以及根据尝试过程中MySQL给出的错误提示,知道自己是在左连接上使用错误了,应该在开始查询出来所有的字段,left join 后不能在使用select * 最后,回想了一遍自己所学的left join的语法,写出了最后的正确的查询结果

SELECT t1.supply_id '供应商ID',t1.supply_name '供应商名称',t1.user_id '供应商绑定的用户ID',t1.withdrawtime '供应商提现次数' ,t1.supplyallmoney '供应商提现金额',t1.payway '供应商提现方式',t1.supply_money '供应商账户余额',t1.supply_free_money '供应商冻结余额(已提现金额)',
t2.total_pay_price '供应商订单总金额',t2.order_id '供应商订单数量'
FROM  (											
SELECT  count(ysw.supply_id) AS withdrawtime,  ysw.user_id AS user_id,   ysw.supply_id  AS supply_id ,  SUM(ysw.money)  AS supplyallmoney,   ysw.alipay_name AS alipay_name ,ysw.alipay_account AS alipay_account,  ysw.audit_time as audit_time ,  ysw.bank_account AS bank_account,   ysw.bank_card AS bank_card,   ysw.bank_name AS bank_name,
case ysw.pay_type when 10 then '微信' when 20 then '支付宝' else '银行卡' end as payway ,
ys.supply_name AS supply_name,  ys.money AS supply_money,  ys.freez_money AS supply_free_money
FROM yoshop_supply_withdraw AS ysw LEFT JOIN yoshop_supply AS ys ON ysw.supply_id = ys.supply_id
WHERE ysw.create_time < 1647446400 AND ysw.apply_status IN (10,20,40) GROUP BY ysw.supply_id
ORDER BY SUM(ysw.money) DESC ) AS t1 
	
 LEFT JOIN

    (SELECT  supply_id  AS 'supply_id' , COUNT(order_id) AS order_id,   SUM(total_pay_price)    AS total_pay_price 
    FROM 	yoshop_order_goods WHERE  create_time < 1647446400 AND order_pay_status = 0  
    AND  order_id IN(
        SELECT order_id FROM yoshop_order WHERE order_status IN (10,30) 
    AND order_id NOT IN (
        SELECT order_id FROM yoshop_order_refund)	 ) 
    GROUP BY supply_id 
    ORDER BY SUM(total_pay_price) DESC ) AS t2
								
ON t1.supply_id = t2.supply_id

正确的结果截图:

MySQL派生表联表查询实战过程

总结:

这次查询的经历使我自己明显的感觉到动手实战才能提升自己的能力,加强自己的记忆,在查询的时候要注意以下几点。第一:一步步的进行查询,不要害怕查询数据的复杂。第二:在派生表中尽量不要使用汉字作为字段名,只在最顶层select 查询最终结果的时候在把字段名 as 为“汉字”,第三:熟悉记忆左连接和union 链接的查询语法。

到此这篇关于MySQL派生表联表查询的文章就介绍到这了,更多相关MySQL派生表联表查询内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
MySQL 可扩展设计的基本原则
May 14 MySQL
linux下导入、导出mysql数据库命令的实现方法
May 26 MySQL
MYSQL 无法识别中文的永久解决方法
Jun 03 MySQL
mysql联合索引的使用规则
Jun 23 MySQL
MySQL令人大跌眼镜的隐式转换
Aug 23 MySQL
mysql的数据压缩性能对比详情
Nov 07 MySQL
SQL基础的查询语句
Nov 11 MySQL
MySQL数据库中varchar类型的数字比较大小的方法
Nov 17 MySQL
教你如何让spark sql写mysql的时候支持update操作
Feb 15 MySQL
你真的会用Mysql的explain吗
Mar 31 MySQL
Mysql 如何合理地统计一个数据库里的所有表的数据量
Apr 18 MySQL
数据设计之权限的实现
Aug 05 MySQL
MySQL学习之基础命令实操总结
Mar 19 #MySQL
MySQL学习之基础操作总结
Mar 19 #MySQL
Pycharm远程调试和MySQL数据库授权问题
Mar 18 #MySQL
MySQL 主从复制数据不一致的解决方法
浅谈redis的过期时间设置和过期删除机制
MySQL读取JSON转换的方式
Mar 18 #MySQL
分享MySQL常用 内核 Debug 几种常见方法
Mar 17 #MySQL
You might like
PHP 和 MySQL 基础教程(一)
2006/10/09 PHP
《PHP边学边教》(02.Apache+PHP环境配置――下篇)
2006/12/13 PHP
使用php+apc实现上传进度条且在IE7下不显示的问题解决方法
2013/04/25 PHP
解析coreseek for sphinx的使用
2013/06/21 PHP
PHP 登录完成后如何跳转上一访问页面
2014/01/14 PHP
PHP实现Google plus的好友拖拽分组效果
2016/10/21 PHP
PHP7.1实现的AES与RSA加密操作示例
2018/06/15 PHP
对laravel in 查询的使用方法详解
2019/10/09 PHP
Laravel框架处理用户的请求操作详解
2019/12/20 PHP
Javascript学习笔记9 prototype封装继承
2010/01/11 Javascript
Jquery调用webService远程访问出错的解决方法
2010/05/21 Javascript
js Array操作的最简短最容易理解方法
2013/12/09 Javascript
javascript 自定义回调函数示例代码
2014/09/26 Javascript
jQuery点缩略图弹出层显示大图片
2015/02/13 Javascript
Javascript中for循环语句的几种写法总结对比
2017/01/23 Javascript
JS仿Base.js实现的继承示例
2017/04/07 Javascript
js canvas实现QQ拨打电话特效
2017/05/10 Javascript
Angular.js ng-file-upload结合springMVC的使用教程
2017/07/10 Javascript
Nodejs 发布自己的npm包并制作成命令行工具的实例讲解
2018/05/15 NodeJs
详解Vue的钩子函数(路由导航守卫、keep-alive、生命周期钩子)
2018/07/24 Javascript
mpvue+vant app搭建微信小程序的方法步骤
2019/02/11 Javascript
vue中的inject学习教程
2019/04/24 Javascript
JS实现京东商品分类侧边栏
2020/12/11 Javascript
Python3中正则模块re.compile、re.match及re.search函数用法详解
2018/06/11 Python
详解python中Numpy的属性与创建矩阵
2018/09/10 Python
Python遍历字典方式就实例详解
2019/12/28 Python
关于CSS Tooltips(鼠标经过时显示)的效果
2013/04/10 HTML / CSS
意大利宠物用品购物网站:Bauzaar
2018/09/15 全球购物
Pretty You London官网:英国拖鞋和睡衣品牌
2019/05/08 全球购物
explicit和implicit的含义
2012/11/15 面试题
AJAX的优缺点都有什么
2015/08/18 面试题
合作协议书格式
2014/08/19 职场文书
2014政府领导班子对照检查材料思想汇报(3篇)
2014/09/26 职场文书
考试作弊检讨书范文
2015/01/27 职场文书
通讯稿格式及范文
2015/07/22 职场文书
遇事可以测出您的见识与格局
2019/09/16 职场文书