【译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正】

原文连接:传送门

当一个CROSS JOIN 表现得如同一个INNER JOIN

在上一章节我提到当你使用一个CROSS JOIN 操作符时候它会产生一个笛卡尔积。然而这并不总是真实的情况。当你使用WHERE 子句对涉及到CROSS JOIN操作符的表的关联进行约束,SQL SERVER便不会产生笛卡尔积。反而它的功能更像是一个正常的 JOIN 操作符。为了演示这种行为,请查看列表5的代码:

SELECT * FROM Product P CROSS JOIN SalesItem S
WHERE P.ID = S.ProductID;
SELECT * FROM Product P INNER JOIN SalesItem S
ON P.ID = S.ProductID;

列表5:两个相等的SELECT语句

列表5的代码包含了两个SELECT语句。第一个语句使用了CROSS JOIN操作符然后使用了一个WHERE子句来定义如何连接CROSS JOIN操作符涉及的两个表。第二个SELECT语句使用了带有一个ON子句的正常的INNER JOIN操作符来关联两个表。SQL SERVER的查询优化器足够智能,可以知道列表5中的第一个SELECT语句可以重写为一个INNER JOIN。一个WHERE子句在此提供了CROSS JOIN操作符涉及的两个表的连接谓词,因此当一个CROSS JOIN操作符和一个WHERE子句配合起来使用的时候,查询优化器便知道它可以重写这个查询。因此SQL SERVER引擎为列表5中的两个查询生成了相同的执行计划。而当你不提供一个WHERE约束的时候,SQL SERVER不知道如何关联CROSS JOIN子句涉及的两个表,于是便在CROSS JOIN操作符相关的两个数据集之间创建了笛卡尔积。

 使用CROSS JOIN来找到未卖出的产品

前面章节出现的示例可以帮助你理解CROSS JOIN操作符以及如何使用它。使用CROSS JOIN操作符的力量之一便是用其找到存在于一个表而在另一张表中没有匹配记录的那些条目。举个例子,假设我想要报告Product表中的每个产品每天的销售量和销售金额,因为在我的例子中,每个ProductName每天没有被销售也会有一个记录。我的报告需求意味着我需要为那些在某一个给定的日期中没有销售的产品展示一个数量0和销售金额为0的记录。而CROSS JOIN操作符与LEFT OUTER JOIN操作符配合起来使用恰好可以帮助我定义这些在某一天没有售出的条目。满足这些报告需求的代码可以在列表6中被找到:

SELECT S1.SalesDate, ProductName
, ISNULL(Sum(S2.Qty),0) AS TotalQty
, ISNULL(SUM(S2.TotalSalesAmt),0) AS TotalSales
FROM Product P
CROSS JOIN
(
SELECT DISTINCT SalesDate FROM SalesItem
) S1
LEFT OUTER JOIN
SalesItem S2
ON P.ID = S2.ProductID
AND S1.SalesDate = S2.SalesDate
GROUP BY S1.SalesDate, P.ProductName
ORDER BY S1.SalesDate;

列表6:使用CROSS JOIN找到没有销售的产品

让我来带你分析这段代码。首先我创建了一个子查询,它获取了所有去重的SalesDate的值。这个子查询给了我所有发生交易的日期。然后我用Product表与其进行CROSS JOIN,这允许我在每个日期和每种产品行之间创建一个笛卡尔积。从CROSS JOIN返回的数据集将会包含我在最终结果集合中需要的每个值--当然除了每个售出产品的Qty和TotalSalesAmt 。为了得到这些汇总列我将CROSS JOIN得到的笛卡尔积与SalesItem表进行了一个LEFT OUTER JOIN关联。我基于ProductID和ProductID列进行了这个关联。通过使用LEFT OUTER JOIN,笛卡尔积中的每一行数据都会被返回,并且如果对于一个ProductID和SalesDate具有一个匹配的SalesDate记录,那么QtyTotalSalesAmt 值便会被关联在期望的行中。这个查询做的最后一件事便是使用GROUP BY子句来基于SalesDate和ProductName来对Qty 和TotalSalesAmount 进行总结。

高级T-SQL进阶系列 (一)【中篇】:使用 CROSS JOIN 介绍高级T-SQL的更多相关文章

  1. 高级T-SQL进阶系列 (一)【上篇】:使用 CROSS JOIN 介绍高级T-SQL

    [译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正] 原文连接:传送门 这是一个新进阶系列的第一篇文章,我们将浏览Transact-SQL(T-SQL)的更多高级特性.这个进阶系列将会包 ...

  2. 高级T-SQL进阶系列 (一)【下篇】:使用 CROSS JOIN 介绍高级T-SQL

    [译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正] 原文链接:传送门. 性能考虑产生了笛卡尔积的这个CROSS JOIN操作符具有一些性能方面的问题需要考虑.因为SQL引擎需要将一个数 ...

  3. SQL进阶系列之7用SQL进行集合运算

    写在前面 集合论是SQL语言的根基,因为这种特性,SQL也被称为面向集合语言 导入篇:集合运算的几个注意事项 注意事项1:SQL能操作具有重复行的集合(multiset.bag),可以通过可选项ALL ...

  4. SQL进阶系列之9用SQL处理数列

    写在前面 关系模型的数据结构里,并没有顺序的概念,但SQL处理有序集合也有坚实的理论基础 生成连续编号 --生成连续编号 CREATE TABLE Digits (digit INTEGER PRIM ...

  5. SQL进阶系列之8EXISTS谓词的用法

    写在前面 支撑SQL和关系数据库的基础理论:数学领域的集合论和逻辑学标准体系的谓词逻辑 理论篇 什么是谓词?谓词是返回值为真值(true false unknown)的函数 关系数据库里,每一个行数据 ...

  6. SQL进阶系列之5外连接的用法

    写在前面 SQL本身是作为一种数据提取工具而出现,使用SQL生成各种定制化报表和非定制化报表并非SQL原本用途的功能,但这并不意味着SQL无法实现这些功能. 用外连接进行行列转换(1)(行 → 列): ...

  7. Linq To Sql进阶系列(六)用object的动态查询与保存log篇

    动态的生成sql语句,根据不同的条件构造不同的where字句,是拼接sql 字符串的好处.而Linq的推出,是为了弥补编程中的 Data != Object 的问题.我们又该如何实现用object的动 ...

  8. SQL进阶系列之12SQL编程方法

    写在前面 KISS -- keep it sweet and simple 表的设计 注意命名的意义 英文字母 + 阿拉伯数字 + 下划线"_" 属性和列 编程的方针 写注释 注意 ...

  9. SQL进阶系列之10HAVING子句又回来了

    写在前面 HAVING子句的处理对象是集合而不是记录 各队,全队点名 --各队,全体点名! CREATE TABLE Teams (member CHAR(12) NOT NULL PRIMARY K ...

随机推荐

  1. mutiprocessing 同步类型,如锁,条件和队列官方案例:

    官方文档:https://docs.python.org/2/library/multiprocessing.html#module-multiprocessing 1. 同步类型,如锁,条件和队列官 ...

  2. js变量提升的坑

    关于js变量提升 变量提升 在js函数内部是可以直接修改全局的变量的,个人感觉是不好的设计, 但是确实存在这个概念 原理: 先查看有没有函数变量bb 查看形参有没有bb 查看全局有没有bb 报错, 找 ...

  3. 利用Xshell5从本机上向Linux(虚拟机中)上传文件

    Xmanager Enterprise 5云盘分享:  http://pan.baidu.com/s/1jIkiQNW 1. 用ifconfig命令查看Linux的IP地址 2. 由于没有IP,所以我 ...

  4. 2.5 【配置环境】多浏览器驱动 (chrome、IE、Firefox)❀

    来源:http://blog.csdn.net/huilan_same/article/details/51896672 http://www.cnblogs.com/thinkCoding/p/64 ...

  5. Ansible - 配置文件

    概述 再水一发 ref Ansible Configuration Settings 1. 查看 概述 查看 配置文件 的默认位置 命令 > ansible --version 结果 confi ...

  6. linux shell ansible 命令详解

    也可以参考ansible 模块介绍的其他文章:https://www.cnblogs.com/guxiaobei/p/8316903.html 安装ansible yum install epel-r ...

  7. 基于Aspectj表达式配置的Spring AOP

    AOP(Aspect-Oriented Programming, 面向切面编程):是一种新的方法论, 是对传统OOP(Object-Oriented Programming, 面向对象编程)的补充. ...

  8. oracle增加字段,循环

    alter table PARAMETETER_CONFIGURATION add (INPUT_IS VARCHAR2(20) ): declare sum_i int:=0; --定义整型变量,存 ...

  9. CapsNet资源

    算法源码: https://github.com/xanderchf/pyCapsNet https://github.com/naturomics/CapsNet-Tensorflow 参考文章: ...

  10. 17,a:img的alt和title有何异同? b:strong与en的异同?

    alt(alt text):为不能显示的图像,窗体或者applets的用户代理,alt属性用来指定替换文字.替换文字的语言用lang属性来指定. eg:下例中将图像作为链接来使用 <a href ...