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主从复制断开的常用修复方法
Apr 07 MySQL
MySQL系列之五 视图、存储函数、存储过程、触发器
Jul 02 MySQL
mysql 直接拷贝data 目录下文件还原数据的实现
Jul 25 MySQL
MySQL8.0升级的踩坑历险记
Nov 01 MySQL
SpringBoot连接MySQL获取数据写后端接口的操作方法
Nov 02 MySQL
MySQL Innodb索引机制详细介绍
Nov 23 MySQL
一次Mysql update sql不当引起的生产故障记录
Apr 01 MySQL
进阶篇之linux环境下安装MySQL数据库
Apr 09 MySQL
MySQL 表锁定 LOCK和UNLOCK TABLES的 SQL语法
Apr 18 MySQL
MySQL慢查询中的commit慢和binlog中慢事务的区别
Jun 16 MySQL
MySQL数据库之内置函数和自定义函数 function
Jun 16 MySQL
MySQL约束(创建表时的各种条件说明)
Jun 21 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入门学习知识点八 PHP中for循环基本应用之九九乘法口绝表
2011/07/14 PHP
PHP与SQL注入攻击防范小技巧
2011/09/16 PHP
微信公众平台天气预报功能开发
2014/07/06 PHP
php采用ajax数据提交post与post常见方法总结
2014/11/10 PHP
php实现基于pdo的事务处理方法示例
2017/07/21 PHP
JavaScript快速检测浏览器对CSS3特性的支持情况
2012/09/26 Javascript
jquery实现鼠标滑过显示提示框的方法
2015/02/05 Javascript
javascript验证香港身份证的格式或真实性
2017/02/07 Javascript
Vue组件化通讯的实例代码
2017/06/23 Javascript
vue数据控制视图源码解析
2018/03/28 Javascript
JavaScript实现微信红包算法及问题解决方法
2018/04/26 Javascript
Layer弹出层动态获取数据的方法
2018/08/20 Javascript
vue 使用自定义指令实现表单校验的方法
2018/08/28 Javascript
jstree中的checkbox默认选中和隐藏示例代码
2019/12/29 Javascript
npx create-react-app xxx创建项目报错的解决办法
2020/02/17 Javascript
[02:20]2014DOTA2西雅图邀请赛 MVP外卡赛首胜采访
2014/07/09 DOTA
wxPython窗口中文乱码解决方法
2014/10/11 Python
python根据出生日期返回年龄的方法
2015/03/26 Python
Python中使用partial改变方法默认参数实例
2015/04/28 Python
python使用urllib2提交http post请求的方法
2015/05/26 Python
Python调用C++程序的方法详解
2017/01/24 Python
Python基于Flask框架配置依赖包信息的项目迁移部署
2018/03/02 Python
Linux(Redhat)安装python3.6虚拟环境(推荐)
2018/05/05 Python
解决Python3 被PHP程序调用执行返回乱码的问题
2019/02/16 Python
Python实现定时监测网站运行状态的示例代码
2020/09/30 Python
CSS3的新特性介绍
2008/10/31 HTML / CSS
澳大利亚领先的睡衣品牌:Peter Alexander
2016/08/16 全球购物
英国最大的在线奢侈手表零售商:Jura Watches
2018/01/29 全球购物
主键(Primary Key)约束和唯一性(UNIQUE)约束的区别
2013/05/29 面试题
机关节能减排实施方案
2014/03/17 职场文书
班级学习计划书
2014/04/27 职场文书
财务经理岗位职责范本
2015/04/08 职场文书
python文件目录操作之os模块
2021/05/08 Python
Anaconda安装pytorch及配置PyCharm 2021环境
2021/06/04 Python
MySQL一些常用高级SQL语句
2021/07/03 MySQL
Python中super().__init__()测试以及理解
2021/12/06 Python