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

原文连接:传送门

当一个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. Vue-cli3 项目配置 Vue.config.js( 代替vue-cli2 build config)

    Vue-cli3 搭建的项目 界面相对之前较为简洁 之前的build和config文件夹不见了,那么应该如何配置 如webpack等的配那 只需要在项目的根目录下新建 vue.config.js 文件 ...

  2. 【转载】Java容器的线程安全

    转自:http://blog.csdn.net/huilangeliuxin/article/details/12615507 同步容器类 同步容器类包括Vector和Hashtable(二者是早期J ...

  3. zk zkCli shell命令

    查看zk 注册服务:在zk bin 下执行 sh zkCli.sh 计入客户端shell命令行 查看zk注册服务:ls  /  或者递归查看 ls  -s  /      列出的为注册服务. 查询服务 ...

  4. dw选择器

    选择器并没有一个固定的定义,在某种程度上说,jQuery的选择器和样式表中的选择器十分相似.选择器具有如下特点:1.简化代码的编写2.隐式迭代3.无须判断对象是否存在jQuery 的选择器可谓之强大无 ...

  5. AcWing 872. 最大公约数

    #include <iostream> #include <algorithm> using namespace std; //辗转相除法 //a和b的最大公约数 = b和(a ...

  6. 吴裕雄 python 机器学习——集成学习梯度提升决策树GradientBoostingRegressor回归模型

    import numpy as np import matplotlib.pyplot as plt from sklearn import datasets,ensemble from sklear ...

  7. laravel Excel导入导出

    1.简介 Laravel Excel 在 Laravel 5 中集成 PHPOffice 套件中的 PHPExcel,从而方便我们以优雅的.富有表现力的代码实现Excel/CSV文件的导入和导出. 该 ...

  8. 题解 SP8284 WEIGHT - Weighted Sum

    SP8284 WEIGHT - Weighted Sum 题意描述 给出长度为n(n<=1e6)的序列A, A中元素可能为正数,可为负数或0,.让你构造一个长度为n的序列W,给这些整数A赋权,使 ...

  9. 空指针异常与Optional类

    一.什么是空指针异常 当程序需要对象实例的时候返回null就会抛出空指针异常(NullPointerException,简称NPE).包括以下情况: 调用一个null对象实例的方法 访问或修饰null ...

  10. PHP固定长度字符串

    /** * 获取固定长度随机字符串 * @param $n * @return string * @throws Exception */ function gf_rand_str($n) { if ...