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

原文连接:传送门

这是一个新进阶系列的第一篇文章,我们将浏览Transact-SQL(T-SQL)的更多高级特性。这个进阶系列将会包含一系列的文章,它们会扩展你在之前的两个TSQL进阶系列所掌握的TSQL的基础。

本系列“高级Transact-SQL”将会包含如下T-SQL主题:

  • 使用CROSS JOIN 操作符
  • 使用APPLY操作符
  • 理解通用表表达式(CTE's)
  • 使用TSQL游标的记录级别处理
  • 使用UNPIVOT实现列转行
  • 使用排序函数对数据进行排序
  • 使用相关函数来操作日期和时间
  • 理解OVER子句的变量

本进阶的读者应该已经很好的理解了如何从数据库表进行查询,更改,插入,删除数据。此外他们应该具有实际的工作经验用以控制TSQL代码的执行流,以及能够测试和操作数据。

本进阶应该可以帮助读者准备通过微软认证考试70-461:查询SQL SERVER 2012.

对于本进阶系列的第一部分,我们将讨论一下CROSS JOIN操作符。

介绍CROSS JOIN 操作符

CROSS JOIN操作符可以用来将一个数据集的所有记录和另一个数据集的所有数据进行比较。通过在两个数据集之间使用CROSS JOIN操作符,你便创建了成为笛卡尔积的东西。

这儿有一个简单的示例,其使用CROSS JOIN操作符来连接两张表A和B:

  1. SELECT * FROM A CROSS JOIN B

注意当使用CROSS JOIN操作符时,没有像你使用INNER,OUTER JOIN 那样,有一个JOIN子句来连接两张表。

你应该意识到使用CROSS JOIN 操作符会产生很大的数据集合。为了浏览这种行为让我们看看两个不同的示例,看看从一个CROSS JOIN产生的数据集会多么的巨大。对于第一个示例我们假设你会交叉连接两个表,其中表A具有10行而表B具有3行,那么结果集合便会具有10*3行或者说是30行。对于第二个示例我们假定表A具有1000万条数据而表B具有300万条数据。那么表A和表B的CROSS JOIN 产生的结果集会有多少条数据呢?那会产生高达30,000,000,000,000条数据。那是许多行并且它会占用SQL SERVER大量的时间和资源来创建结果集。因此当在大的记录集合上使用CROSS JOIN操作符时,你需要特别小心。

让我们通过几个示例来更近一点查看CROSS JOIN 操作符。

使用CROSS JOIN操作符的基本示例

对于第一组示例我们将连接两个示例表。列表1的代码用来创建这两个示例表。确保你在一个用户数据库上执行此脚本而不是在master库上。

  1. CREATE TABLE Product (ID int,
  2. ProductName varchar(100),
  3. Cost money);
  4. CREATE TABLE SalesItem (ID int,
  5. SalesDate datetime,
  6. ProductID int,
  7. Qty int,
  8. TotalSalesAmt money);
  9. INSERT INTO Product
  10. VALUES (1,'Widget',21.99),
  11. (2,'Thingamajig',5.38),
  12. (3,'Watchamacallit',1.96);
  13. INSERT INTO SalesItem
  14. VALUES (1,'2014-10-1',1,1,21.99),
  15. (2,'2014-10-2',3,1,1.96),
  16. (3,'2014-10-3',3,10,19.60),
  17. (4,'2014-10-3',1,2,43.98),
  18. (5,'2014-10-3',1,2,43.98);

列表1 CROSS JOIN的测试表

对于第一个CROSS JOIN 示例,我们将运行列表2的代码。

  1. SELECT * FROM
  2. Product CROSS JOIN SalesItem;

列表2:简单的CROSS JOIN示例

当我们在SSMS窗口运行列表2的代码时,在我的结果窗口我们得到了报告1的输出:

  1. ID ProductName Cost ID SalesDate ProductID Qty TotalSalesAmt
  2. --- --------------------- -------- ---- ----------------------- --------- ---- ---------------
  3. 1 Widget 21.99 1 2014-10-01 00:00:00.000 1 1 21.99
  4. 1 Widget 21.99 2 2014-10-02 00:00:00.000 3 1 1.96
  5. 1 Widget 21.99 3 2014-10-03 00:00:00.000 3 10 19.60
  6. 1 Widget 21.99 4 2014-10-03 00:00:00.000 1 2 43.98
  7. 1 Widget 21.99 5 2014-10-03 00:00:00.000 1 2 43.98
  8. 2 Thingamajig 5.38 1 2014-10-01 00:00:00.000 1 1 21.99
  9. 2 Thingamajig 5.38 2 2014-10-02 00:00:00.000 3 1 1.96
  10. 2 Thingamajig 5.38 3 2014-10-03 00:00:00.000 3 10 19.60
  11. 2 Thingamajig 5.38 4 2014-10-03 00:00:00.000 1 2 43.98
  12. 2 Thingamajig 5.38 5 2014-10-03 00:00:00.000 1 2 43.98
  13. 3 Watchamacallit 1.96 1 2014-10-01 00:00:00.000 1 1 21.99
  14. 3 Watchamacallit 1.96 2 2014-10-02 00:00:00.000 3 1 1.96
  15. 3 Watchamacallit 1.96 3 2014-10-03 00:00:00.000 3 10 19.60
  16. 3 Watchamacallit 1.96 4 2014-10-03 00:00:00.000 1 2 43.98
  17. 3 Watchamacallit 1.96 5 2014-10-03 00:00:00.000 1 2 43.98

报告1:当运行列表2的结果

如果你查看报告1的结果你将会发现会有15条不同的记录。前5条记录包含了列值,是从Product表的第一行与SalesItem 表的5条不同的记录进行连接。同样对于Product表的第二行与第三行也是如此。最终返回的总行数是Product表的行数乘以SalesItem 表的行数,也就是15。

为什么产生笛卡尔积是有用的一个原因或许是为了产生测试数据。假设我想要使用Product表和SalesItem表的数据产生一些测试数据,我便可以使用CROSS JOIN来做这个,如同我在列表3中所做的:

  1. SELECT ROW_NUMBER() OVER(ORDER BY ProductName DESC) AS ID,
  2. Product.ProductName
  3. + CAST(SalesItem.ID as varchar(2)) AS ProductName,
  4. (Product.Cost / SalesItem.ID) * 100 AS Cost
  5. FROM Product CROSS JOIN SalesItem;

列表3:简单的CROSS JOIN示例

当我运行列表3的代码我得到报告2的输出:

  1. ID ProductName Cost
  2. ----- ----------------------------------------------------------- ---------------------
  3. 1 Widget1 2199.00
  4. 2 Widget2 1099.50
  5. 3 Widget3 733.00
  6. 4 Widget4 549.75
  7. 5 Widget5 439.80
  8. 6 Watchamacallit1 196.00
  9. 7 Watchamacallit2 98.00
  10. 8 Watchamacallit3 65.33
  11. 9 Watchamacallit4 49.00
  12. 10 Watchamacallit5 39.20
  13. 11 Thingamajig1 538.00
  14. 12 Thingamajig2 269.00
  15. 13 Thingamajig3 179.33
  16. 14 Thingamajig4 134.50
  17. 15 Thingamajig5 107.60

报告2:当运行列表3的结果

如你所见通过查看列表3的代码我生成了许多数据行,它们包含了和Product表的数据相似的数据。通过使用ROW_NUMBER函数我们能够在每一行生成唯一列。另外我使用SalesItem 表的ID列来创建ProductNameCost 列的值。产生的行数等于Product 表的行数乘以SalesItem 表的行数。

到现在为止本节的示例仅仅展示了两个表之间的CROSS JOIN。你也可以使用CROSS JOIN操作符来进行多个表的CROSS JOIN。列表4的示例展示了三个表的笛卡尔积。

  1. SELECT * FROM sys.tables
  2. CROSS JOIN sys.objects
  3. CROSS JOIN sys.sysusers;

列表4:使用CROSS JOIN创建三个表的笛卡尔积

从运行列表4的输出具有两个不同的CROSS JOIN操作符。从这代码创建的笛卡尔积将会产生一个结果集,它的总行数等于sys.tables表的行数乘以sys.objects表的行数再乘以sys.sysusers表的行数。

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

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

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

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

    [译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正] 原文连接:传送门. 当一个CROSS JOIN 表现得如同一个INNER JOIN 在上一章节我提到当你使用一个CROSS JOIN ...

  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. hdu 6214 Smallest Minimum Cut(最小割的最少边数)

    题目大意是给一张网络,网络可能存在不同边集的最小割,求出拥有最少边集的最小割,最少的边是多少条? 思路:题目很好理解,就是找一个边集最少的最小割,一个方法是在建图的时候把边的容量处理成C *(E+1 ...

  2. c++中const变量定义与头文件包含的有关问题

    在使用C++进行程序开发的时候,有个常识我们很熟悉,就是把类的定义写在.h文件中,把类的具体实现写在.cpp文件中.这毫无疑问是对的.但我们很少去思考为什么要这样做,本文结合自己的学习体会,对头文件及 ...

  3. c语言getipaddrtable获得ip地址与sendArp获得mac地址以及一些字节序问题记录

    https://docs.microsoft.com/zh-cn/windows/win32/api/iphlpapi/nf-iphlpapi-getipaddrtable msdn,有很多c的源码还 ...

  4. Linux下查看进程和端口信息

    1.根据进程名查看进程信息,以查看tomcat进程名为例,查看所对应的进程id为1095(或者使用: ps -aux | grep tomcat 查看占用内存等信息) ps -ef | grep to ...

  5. 040_字符串连接符 041_条件运算符目 042_运算符优先级_逻辑与或优先问题 043_自动类型转化 044_强制类型转换 045_基本类型常见错误_溢出_L问题

    040_字符串连接符 package test_package; /** * 字符串运算符 * @author * */public class TestOperator05 { public sta ...

  6. 【游戏体验】Colour My World(让我的世界充满色彩)

    这是一款玩法简单的游戏 但是它给你的感觉不一样 推荐试玩 个人测评 游戏性 7/10 音乐 9/10 剧情 6/10 总评 22/30

  7. TestNG单元测试与使用详解

    TestNG的基本注解与执行顺序 在类里编辑程序时,在@Test后面,摁 alt+回车,选择对应的插件,可以把目前用到的插件自动添加到 pom.xml 文件中,如下面的testng,每摁一次,就多添加 ...

  8. django view 视图控制之数据返回的视图函数

    八.视图 view 概述:views.py定义的python函数,它接受Web请求并且返回Web响应. 有几个页面就有几个视图view user出入url地址,发送request--->urls ...

  9. VS Code的git配置

    最近打算使用VS Code作为python的编辑器,这里记录一下VS Code中git的配置方法 因为vscode中git只是使用本地的git,所以本地必须先安装git才行. 1.git的安装 git ...

  10. 树莓派安装中文输入法Fcitx及Google拼音输入法

    本来是想给树莓派安装搜狗输入法的, 搜狗输入法Linux版:https://pinyin.sogou.com/linux/?r=pinyin 但是一直安装不成功,后面发现原来是系统架构不同导致的,搜狗 ...