使用LEFT JOIN 统计左右存在的数据
最近做了一个数据模块的统计,统计企业收款、发票相关的数据,开始统计是比较简单,后面再拆分账套统计就有点小复杂,本文做一个简单的记录。
需求
企业表
企业表t_company
有如下字段:标识id
、企业名称name
:
id | name |
---|---|
1 | 腾讯 |
2 | 百度 |
收款表
企业对应有收款表t_collection
有如下字段:标识id
、账套account
、企业idcompany_id
、收款金额amount
:
id | account | company_id | amount |
---|---|---|---|
1 | 1 | 1 | 30 |
2 | 2 | 1 | 20 |
3 | 1 | 2 | 30 |
4 | 2 | 2 | 40 |
开票表
开票表t_invoice
有如下字段:标识id
、账套account
、企业idcompany_id
、发票金额amount
:
id | account | company_id | amount |
---|---|---|---|
1 | 1 | 1 | 10 |
2 | 2 | 1 | 20 |
3 | 1 | 2 | 30 |
4 | 2 | 2 | 50 |
汇总企业统计
现在要做一个统计,统计企业收款金额,以及发票金额,需要将收款表和发票表将company_id
做group up
操作。开票表也是做类似的操作,企业表和上面的结果做left join
连接操作,sql
如下:
select tc.id,tc.name,tc2.amount as collection_amount,ti.amount as invoice_amunt from t_company tc
left join (
select company_id,sum(amount) as amount from t_collection group by company_id
) tc2 on tc.id = tc2.company_id
left join (
select company_id,sum(amount) as amount from t_invoice group by company_id
) ti on tc.id = ti.company_id
查询结果:
id | name | collection_amount | invoice_amunt |
---|---|---|---|
1 | 腾讯 | 50 | 30 |
2 | 百度 | 70 | 80 |
再分账套做汇总(重点)
在上面统计的基础上,再拆分账套统计。
收款表和发票表做账套的拆分,和企业表做关联:
select tc.id,tc.name,tc2.amount as collection_amount,ti.amount as invoice_amunt from t_company tc
left join (
select company_id,account,sum(amount) as amount from t_collection
group by company_id,account
) tc2 on tc.id = tc2.company_id
left join (
select company_id,account,sum(amount) as amount from t_invoice
group by company_id,account
) ti on tc.id = ti.company_id and tc2.account = ti.account
首先是将收款表做账套的拆分,然后关联发票表的账套拆分。看似没有问题,但是left join
返回左边的所有记录,以及右边字段相等的数据。
这样就有一个问题:
如果左边表没有的数据,右边的表也不会查出来。比如以上查询收款表不存在的账套,发票表存在账套也不会查出来。这就是
left join
的局限性。
全表连接解决方案一:
MySQL
有left join
、right join
应该也有full join
全表连接。
但是
MySQL
是不支持full join
全表连接。
网上也有解决方案使用union
替换full_join
,思路是左表左连接右边,左表右连接右边,将上面的两个结果union
连接起来:
select * from t1 left join t2 on t1.id = t2.id
union
select * from t1 right join t2 on t1.id = t2.id;
上面只是两个表的关联,如果三个表或者更多的关联,写起来就比较繁琐了。
全表连接解决方案二:
全表连接就是一个没有限制的左表连接,就是去掉on
关联条件,
要left join
所有的账套,首先要显示全所有的账套,企业表
关联账套表
,但是两个表是没有关联的,需要去掉on
后面的关联条件,但是MySQL
语法连接后面必须要加on
,将约束条件改成1 = 1
即可:
select tc.id,tc.name,ta.id as account from t_company tc left join t_account ta on 1 = 1
id | name | account |
---|---|---|
1 | 腾讯 | 1 |
1 | 腾讯 | 2 |
2 | 百度 | 1 |
2 | 百度 | 2 |
查询出所有的公司账套之后,再left join
收款表和发票表:
select tc.id,tc.name,tc.account,tc2.amount as collection_amount,ti.amount as invoice_amunt from (
select tc.id,tc.name,ta.id as account from t_company tc left join t_account ta on 1 = 1
)tc
left join (
select company_id,account,sum(amount) as amount from t_collection group by company_id,account
) tc2 on tc.id = tc2.company_id and tc.account = tc2.account
left join (
select company_id,account,sum(amount) as amount from t_invoice group by company_id,account
) ti on tc.id = ti.company_id and tc.account = ti.account
结果:
id | name | account | collection_amount | invoice_amunt |
---|---|---|---|---|
1 | 腾讯 | 1 | 30 | 10 |
1 | 腾讯 | 2 | 20 | 20 |
2 | 百度 | 1 | 30 | 30 |
2 | 百度 | 2 | 40 | 50 |
总结
- 企业分组统计收款和发票表,只需要对企业做
group by
分组即可。 - 企业和账套一起分组,
left join
只会统计左边存在的数据,而需要统计两边都存在的数据。- 使用
union
多表查询比较繁琐。 left join
使用on 1 = 1
查询不添加限制条件,查询所有公司的账套,再关联发票和收款。
- 使用
参考
使用LEFT JOIN 统计左右存在的数据的更多相关文章
- 从数据表中随机抽取n条数据有哪几种方法(join实现可以先查数据然后再拼接)
从数据表中随机抽取n条数据有哪几种方法(join实现可以先查数据然后再拼接) 一.总结 一句话总结:最好的是这个:"SELECT * FROM table WHERE id >= (( ...
- 分享一个Python脚本--统计redis key类型数据大小分布
概述 今天主要介绍怎么统计redis key类型数据大小分布. 原理:使用redis命令: scan.pipline.type 和 debug object 来得到 redis key 信息. 脚本 ...
- Mysql统计每年每个月的数据——详细教程
Mysql统计每年每个月的数据(前端页面统计图实现) 最终想实现的效果图,在这里就不多废话了,直接上效果图,由于测试数据有几个月是为0的,所以数据图看着会有点怪怪. 接下来是数据库的两个表,这里直接给 ...
- 记录sql中统计近五天数据的口径(While+IF)
话不多说,直接上码↓ IF OBJECT_ID('tempdb..#Table') IS NOT NULL BEGIN DROP TABLE #Table; END; DECLARE @tbRange ...
- shell 统计GMT0 时区的数据
和某个供应商核对数据,对方是GMT+0时区,我方报表默认北京时间,无法修改为GMT0, 对excel中按照小时级别的数据导出到excel处理,然后转为文本文件,shell转为GMT0进行统计: 前期处 ...
- mysql join 的同时可以筛选数据
看sql ) ) group by a.id; 这里面用了多个子查询,与join关联. 其中 不仅有关联条件,还对sh_mall_goods表进行了筛选,只选出mall_id为9的数据,进行关联. 这 ...
- VBA怎样统计同一类型的数据的总和
今天是2014-11-01 是周末,忙了一周了,最终能够闲下来了.想起近期工作用到的VBA的一个场景,结合VBA的数组,所以就想试试看.结果还好.出来了.这年头,又玩起了VB了,经过多时才接受了VB的 ...
- 下单快发货慢:一个 JOIN SQL 引起 SqlClient 读取数据慢的奇特问题
最近遇到一个非常奇特的问题,在一个 ASP.NET Core 项目中从 SQL Server 2008 R2 中查询获取 100 条记录竟然耗时 10 多秒,如果是查询本身慢,那到不是什么奇特的问题. ...
- 使用MTA HTML5统计API来分析数据
使用MTA HTML5统计API来分析数据 在开发个人博客的时候,用到了腾讯移动分析(MTA),相比其他数据统计平台来说我喜欢她的简洁高效,易上手,同时文档也比较全面,提供了数据接口供用户调用. 在看 ...
随机推荐
- MySQL查询性能优化七种武器之索引潜水
有读者可能会一脸懵逼? 啥是索引潜水? 你给起的名字的吗?有没有索引蛙泳? 这个名字还真不是我起的,今天要讲的知识点就叫索引潜水(Index dive). 先要从一件怪事说起: 我先造点数据复现一下问 ...
- vue2与vue3实现响应式的原理区别和提升
区别: vue2.x: 实现原理: 对象类型:Object.defineProperty()对属性的读取,修改进行拦截(数据劫持): 数组类型:通过重写更新数组的一系列方法来进行拦截(对数组的变更方法 ...
- Two---python循环语句/迭代器生成器/yield与return/自定义函数与匿名函数/参数传递
python基础02 条件控制 python条件语句是通过一条或多条语句的执行结果(Ture或者False)来执行的代码块 python中用elif代替了else if,所以if语句的关键字为:if- ...
- Luogu4427 [BJOI2018]求和 (树上差分)
预处理,树上差分.注意深度减一 #include <cstdio> #include <iostream> #include <cstring> #include ...
- Git 02 安装
参考源 https://www.bilibili.com/video/BV1FE411P7B3?spm_id_from=333.999.0.0 版本 本文章基于 Git 2.35.1.2 这里以安装 ...
- 052_末晨曦Vue技术_处理边界情况之程序化的事件侦听器
程序化的事件侦听器 点击打开视频讲解更详细 现在,你已经知道了 $emit 的用法,它可以被 v-on 侦听,但是 Vue 实例同时在其事件接口中提供了其它的方法.我们可以: 通过 $on(event ...
- PicGo+GitHub 图床搭建
前言 用GitHub搭建图床,在很久之前我就有了解,但由于市面上有挺多免费的图床,比如我之前一直在用的 路过图床,所以一直懒得动手搭建GitHub图床.一直到前两天我在完善博客的相册时,发现 路过图床 ...
- 并发编程二、CPU多级缓存架构与MESI协议的诞生
前言: 文章内容:线程与进程.线程生命周期.线程中断.线程常见问题总结 本文章内容来源于笔者学习笔记,内容可能与相关书籍内容重合 偏向于知识核心总结,非零基础学习文章,可用于知识的体系建立,核心内容 ...
- C++ 初识函数模板
1. 前言 什么是函数模板? 理解什么是函数模板,须先搞清楚为什么需要函数模板. 如果现在有一个需求,要求编写一个求 2 个数字中最小数字的函数,这 2 个数字可以是 int类型,可以是 float ...
- 【android 逆向】arm if
#include <stdio.h> void if1(int n){ //if else语句 if(n < 10){ printf("the number less th ...