Amt money);
SETNOCOUNT ON;
DECLARE@I int=0;
DECLARE@Date date;
WHILE@I
BEGIN
SET@I =@I +1;
SET@Date =DATEADD(mm,-2,'2014-11-01');
INSERTINTOCust
VALUES(@I,
'Customer #'+right(cast(@I+100000 asvarchar(6)),5));
WHILE@Date
BEGIN
IF@I%7 >0
INSERTINTOSales (CustID,SaleDate,SalesAmt)
VALUES(@I,@Date,10.00);
SET@Date =DATEADD(DD,1,@Date);
END
END
7中的代码为1000个不同的客户创建了价值2个月的数据。代码添加每7个客户的不销售数据。此代码生成1000客户表记录和52 338销售表记录。
为了演示如何用交叉连接的不同操作取决于使用交叉输入集合的大小,让我运行8和9中的代码。对于每个测试,我会记录每个测试返回结果所需的时间。
SELECTCONVERT(CHAR(6),S1.SaleDate,112)ASSalesMonth,C.CustName,
ISNULL(SUM(S2.SalesAmt),0)ASTotalSales
FROMCust C
CROSSJOIN
(
SELECTSaleDate FROMSales
)ASS1
LEFTOUTERJOIN
Sales S2
ONC.ID =S2.CustID
ANDS1.SaleDate =S2.SaleDate
GROUP BYCONVERT(CHAR(6),S1.SaleDate,112),C.CustName
HAVINGISNULL(SUM(S2.SalesAmt),0)=0
ORDERBYCONVERT(CHAR(6),S1.SaleDate,112),C.CustName
SELECTCONVERT(CHAR(6),S1.SaleDate,112)ASSalesMonth,C.CustName,
ISNULL(SUM(S2.SalesAmt),0)ASTotalSales
FROMCust C
CROSSJOIN
(
SELECTDISTINCTSaleDate FROMSales
)ASS1
LEFTOUTERJOIN
Sales S2
ONC.ID =S2.CustID
ANDS1.SaleDate =S2.SaleDate
GROUP BYCONVERT(CHAR(6),S1.SaleDate,112),C.CustName
HAVINGISNULL(SUM(S2.SalesAmt),0)=0
ORDERBYCONVERT(CHAR(6),S1.SaleDate,112),C.CustName
在8中,交叉连接运算符连接了1000个客户有52 338项记录来生成一组52338000行的记录集,然后用于确定一个月内销售为零的客户。在9中,我从销售表只返回一组不同的销售日期价值观。这个不同的集合只产生61个不同的销售日期值,因此清单9中交叉连接操作的结果只生成61000条记录。通过减少交叉连接操作的结果集, 9中的查询的运行时间不到1秒,而8中的代码在我的计算机上运行19秒。造成这种时间差异的主要原因是SQL Server需要为每个查询执行的不同操作处理大量记录。如果你查看两个列表的执行计划,将你会发现计划略有不同。但是,如果你从嵌套循环操作生成的大概记录数看,在图形计划的右侧,你将会看到8大约有52338000条记录,然而9中的相同操作只有大约61000条记录。8查询计划从交叉连接嵌套循环操作被传递到几个附加操作在这个巨大记录集中。因为8中的所有这些操作都针对5200万条记录。所以8比9慢很多。
正如你所见,交叉连接操作中使用的记录数量会明显影响查询运行的时长。因此如果你可以以最小化交叉连接操作中涉及的记录数来编写你的查询,则你的查询的执行效率将大大提高。
结论
交叉连运算符作在两个记录集之间生成笛卡尔乘积。这运算符有助于识别一个表在另一个表中没有匹配记录的项。应该注意交叉连接运算符一起使用的记录集的最小值的大小。通过确保交叉连接的结果集尽可能小,你将确保代码尽可能快地运行。
问题和回答
在本节中,你可以通过回答以下问题来回顾你对交叉连接运算符的理解。
问题1
交叉联接运算符通过匹配两个记录集在ON子句指定的列的基础上来创建结果集。(对的还是错)?
对的
错的
问题2
哪个公式可以用来区分从两个表A和表B之间的无约束交叉联接返回的行数,当表A和表B包含重复行时?
表A中的行数乘以表B中的行数
表A中的行数乘以表B中的唯一行的数
表A中的唯一行的数乘以表B中的行数
表A中的唯一行的数乘以表B中的唯一行的数
问题3
哪种方法提供了减小交叉连接操作产生的笛卡尔乘积大小的最佳机会?
确保连接的两组的行尽可能多
确保连接的两组的行尽可能少
确保交叉连接操作左边的集的行尽可能少
确保交叉连接操作右边的集的行尽可能少
回答
问题1
正确答案是b。交叉连接运算符不使用ON子句执行交叉连接操作。它将一个表中的每一行连接到另一个表中的每一行。在连接两个集合时交叉连接创建笛卡尔乘积。
问题2
正确答案是a、b、c,d不正确,因为当为交叉连接操作创建笛卡尔积时表A或B中重复行也参加。
问题3
正确的答案是b。通过减小交叉连接操作中涉及的两个集合的大小,可以最小化由交叉链接操作创建的最终集合的大小。c和d还有助于减小由交叉连接操作创建的最后集的大小,但可能不确保交叉连接操作中涉及的两个集具有最少的行。