【数据蒋堂】第 31 期:JOIN 简化 – 维度对齐

我们先把上一期中双子表对齐例子的 SQL 写出来:

 SELECT Orders.id, Orders.customer, A.x, B.y FROM Orders  LEFT JOIN (SELECT id,SUM(price) x FROM OrderDetail GROUP BY id ) A ON Orders.id=A.id  LEFT JOIN (SELECT id,SUM(amount) y FROM OrderPayment GROUP BY id ) B ON Orders.id=B.id  WHERE A.x > B.y SELECT Orders.id, Orders.customer, A.x, B.y FROM Orders  LEFT JOIN (SELECT id,SUM(price) x FROM OrderDetail GROUP BY id ) A ON Orders.id=A.id  LEFT JOIN (SELECT id,SUM(amount) y FROM OrderPayment GROUP BY id ) B ON Orders.id=B.id  WHERE A.x > B.y

那么问题来了,这显然是个有业务意义的 JOIN,它算是前面所说的哪一类呢?

这个 JOIN 涉及了表 Orders 和子查询 A 与 B,仔细观察会发现,子查询带有 GROUP BY id 的子句,显然,其结果集将以 id 为主键。这样,JOIN 涉及的三个表(子查询也算作是个临时表)的主键是相同的,它们是一对一的同维表,仍然在前述的范围内。

但是,这个同维表 JOIN 却不能用上一期说的写法简化,子查询 A,B 都不能省略不写。

可以简化书写的原因在于:我们假定事先知道数据结构中这些表之关联关系。用技术术语的说法,就是知道数据库的元数据(metadata)。而对于临时产生的子查询,显然不可能事先定义在元数据中了,这时候就必须明确指定要 JOIN 的表(子查询)。

不过,虽然 JOIN 的表不能省略,但关联字段总是主键,已经在 GROUP BY 中写过了,就没有必要再写一遍了;而且,子查询的主键总是由 GROUP 产生,而 GROUP BY 的字段一定要被选出用于做外层 JOIN,也没必要在 GROUP 和 SELECT 中各写一次;并且这几个子查询涉及的子表是互相独立的,它们之间不会再有关联计算了,我们就可以把 GROUP 动作以及聚合式直接放到主句中,从而消除一层子查询:

 SELECT Orders.id, Orders.customer, OrderDetail.SUM(price) x, OrderParyment.SUM(amount) y  FROM Orders LEFT JOIN OrderDetail GROUP BY id LEFT JOIN OrderPayment GROUP BY id  WHERE A.x > B.y SELECT Orders.id, Orders.customer, OrderDetail.SUM(price) x, OrderParyment.SUM(amount) y  FROM Orders LEFT JOIN OrderDetail GROUP BY id LEFT JOIN OrderPayment GROUP BY id  WHERE A.x > B.y

这里的 JOIN 和 SQL 定义的 JOIN 运算已经差别很大,完全没有笛卡尔积的意思了。而且,也不同于 SQL 的 JOIN 运算将定义在任何两个表之间,这里的 JOIN,OrderDetail 和 OrderPayment 以及 Orders 都是向共同的主键 id 靠拢,即所有表都向某一套基准维度对齐。而由于各表的维度(主键)不同,对齐时可能会有 GROUP BY,在引用该表字段时就会相应地出现聚合运算。OrderDetail 和 OrderPayment 甚至 Orders 之间都不直接发生关联,在书写运算时当然就不用关心它们之间的关系,甚至不必关心另一个表是否存在。而 SQL 那种笛卡尔积式的 JOIN 则总要找一个甚至多个表来定义关联,一旦减少或修改表时就要同时考虑关联表,增大理解难度。

我们称这种 JOIN 称为维度对齐,它并不超出我们前面说过的三种 JOIN 范围,但确实在语法描述上会有不同,这里的 JOIN 不象 SQL 中是个动词,却更象个连词。而且,和前面三种基本 JOIN 中不会或很少发生 FULL JOIN 的情况不同,维度对齐的场景下 FULL JOIN 并不是很罕见的情况。

虽然我们从主子表的例子抽象出维度对齐,但这种 JOIN 并不要求 JOIN 的表是主子表(事实上从上一篇的语法可知,主子表运算还不用写这么麻烦),任何多个表都可以这么关联,而且关联字段也完全不必要是主键或主键的部分。

设有合同表,回款表和发票表:

Contract 合同表

id合同编号date签订日期customer客户price合同金额……

Payment 回款表

seq回款序号date回款日期source回款来源amount金额……

Invoice 发票表

code 发票编号

date 开票日期

customer 客户

amount 开票金额

现在想统计每一天的合同额、回款额以及发票额,就可以写成:

 SELECT Contract.SUM(price), Payment.SUM(amount), Invoice.SUM(amount)  FROM Contract GROUP BY date FULL JOIN Payment GROUP BY date FULL JOIN Invoice GROUP BY date SELECT Contract.SUM(price), Payment.SUM(amount), Invoice.SUM(amount)  FROM Contract GROUP BY date FULL JOIN Payment GROUP BY date FULL JOIN Invoice GROUP BY date

这几种 JOIN 情况还可能混合出现。

延用上面的合同表,再有客户表和销售员表

Customer 客户表

|—|—|

|id| 客户编号 |

|name| 客户名称 |

|area| 所在地区 |

|…|…|

Sales 销售员表

id员工编号name姓名area负责地区……

其中 Contract 表中 customer 字段是指向 Customer 表的外键。

现在我们想统计每个地区的销售员数量及合同额:

 SELECT Sales.COUNT(1), Contract.SUM(price)  FROM Sales GROUP BY area FULL JOIN Contract GROUP BY customer.area SELECT Sales.COUNT(1), Contract.SUM(price)  FROM Sales GROUP BY area FULL JOIN Contract GROUP BY customer.area

维度对齐可以和外键属性化的写法配合合作。

这些例子中,最终的 JOIN 都是同维表。事实上,维度对齐还有主子表对齐的情况,不过相对罕见,我们将在后续仔细讲解维度概念时再涉及,上述写法中其实还有个小漏洞,有了明确的维度定义后才能将这个漏洞补上。

sql三个表join_「数据蒋堂」第 31 期:JOIN 简化 – 维度对齐相关推荐

  1. 代码实现sql编译器_【数据蒋堂】第 19 期:从 SQL 语法看集合化

    [数据蒋堂]第 19 期:从 SQL 语法看集合化 SQL 作为最常用的结构化数据计算语言,虽然在做一些细致处理时不太方便,但用于描述基本运算还是比 Java 等高级语言要简单许多.这是因为 SQL ...

  2. 「数据游戏」:使用 ARIMA 算法预测三日后招商银行收盘价

    作者:天琼,「数据游戏」优胜队伍成员 介绍 本文整理记录了参与的一次小型数据分析竞赛「数据游戏」,竞赛目标是预测2019年5月15日A股闭市时招商银行600036的股价. 主要思路是利用ARIMA算法 ...

  3. SQL Server两表比对数据

    sql server两表比对数据是否完全一直 使用sql server的tablediff工具进行比对 打开cmd cd切换路径到你sqlserver数据库的这个目录下:Microsoft SQL S ...

  4. SQL语句创建表并添加数据

    SQL语句创建表并添加数据 创建表 use school 指定要用的数据库 go create table student 创建表 ( ID bigint identity(1,1), 添加ID,id ...

  5. 【SQL】 使用SQL语句在表中添加数据(一条 / 多条)

    [SQL] 使用SQL语句在表中添加数据(一条 / 多条) 1.单条数据 insert into 表名(字段名1,字段名2)value(值1,值2); 例如: insert into tablenam ...

  6. 「数据ETL」从数据民工到数据白领蜕变之旅(五)-使用dotNET脚本实现SSIS无限扩展...

    在前面一文中,正式引出了SSIS专业数据ETL工具,笔者仅能作引路作用,未能使用文章的方式给大家写出更多的入门级的文章,希望读者们可以自行根据分享的学习资源自行完成入门及进阶的学习. 同时也想给大家分 ...

  7. 【数据蒋堂】第15期:开放的计算能力为数据库瘦身

    [数据蒋堂]第14期:计算封闭性导致臃肿的数据库 我们在上一期谈到,数据库的臃肿,也就是过多的中间表以及相关存储过程,是由于其计算封闭性造成的.如果能够实现独立的计算引擎,使计算不再依赖于数据库提供, ...

  8. 从「猜画小歌」,谈企业的「数据困惑」该何去何从?

    「猜画小歌」坐拥5000万组大数据,你怎么看? Google很会玩. 当所有做云计算.大数据.手机的厂商在广而告之其先进的技术能力时,通常采用直白宣讲式的说教,落地的东西却很少,听多了也就是过眼烟云. ...

  9. 不让「数据孤岛」成为 AI 发展的绊脚石,「联邦学习」将成突破口?...

    雷锋网 AI 科技评论按:人工智能经过漫长发展,近些年成功突破技术与算力上的限制,因此得以在新世纪发挥着举足轻重的作用.不过随之而来是一系列的新问题--最典型的比如「数据孤岛」问题.该问题一日不被解决 ...

最新文章

  1. Don’t Use the Win32 API PostThreadMessage() to Post Messages to UI Threads(翻译)
  2. IntelliJ IDEA 2020.3 重大特性
  3. Kali Linux常用服务配置教程获取IP地址
  4. 【转】ArcGIS.Server.9.2.DotNet的ADF的Toolbar工作过程分析
  5. 按 字节截取分别以GBK 和 utf-8 编码的 字符串的java程序。
  6. 【Vue2.0】—github小案例(二十三)
  7. 短信猫软件的实现(C#)九7bitPDU的编码
  8. Linux CentOS 7 JDK7 Tomcat7 的配置
  9. 数学建模第六章 微分方程建模
  10. Atitit IT办公场所以及度假村以及网点以及租房点建设之道 attilax总结
  11. chmod 755 究竟是什么鬼?
  12. 民间借贷红线大幅下调,二手车平台去金融化将成趋势?
  13. VUE中switch使用
  14. 定点补码加减法运算_定点加减法运算与溢出判断处理
  15. 毕设——基于SpringBoot的电影荐评系统
  16. Android ANR日志分析进行曲
  17. gif动图表情包如何制作?教你一键生成gif表情包
  18. java response 输出word_如何使用java代码导出word
  19. 用计算机表白的数字,用数字表白的暗语
  20. 1118 - Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMI

热门文章

  1. 使用栈实现队列 Implement Queue using Stacks
  2. Oracle数据库备份恢复,巡检须要关注的对象设置以及相关恢复概述
  3. redis 持久化 + 主从复制+ 集群
  4. zabbix通过JMX监控Tomcat及一些报错
  5. 逆向Android软件的步骤
  6. 剖析ASSERT函数
  7. 网页字体设置你了解吗?
  8. 期待flash三剑客
  9. leetcode99. 恢复二叉搜索树(优先队列)
  10. leetcode516. 最长回文子序列(动态规划)