日期:2012-08-03 12:47:00 来源:本站整理
SQL Join的一些总结(实例)[MSSQL防范]
本文“SQL Join的一些总结(实例)[MSSQL防范]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
1.1.1 择要
Join是关系型数据库系统的重要操作之一,SQL Server中包含的常用Join:内联接、外联接和穿插联接等.假如我们想在两个或以上的表获得此中从一个表中的行与另一个表中的行匹配的数据,这时我们应当考虑利用Join,因为Join具体联接表或函数举行查询的特点
本文将通过具体例子介绍SQL中的各种常用Join的特点和利用场所:
1.1.2 正文
首先我们在tempdb中辨别定义三个表College、Student和Apply,具体SQL代码以下:
复制代码 代码以下:
USE tempdb
---- If database exists the same name datatable deletes it.
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'College') DROP TABLE College;
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Student') DROP TABLE Student;
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Apply') DROP TABLE Apply;
---- Create Database.
create table College(cName nvarchar(50), state text, enrollment int);
create table Student(sID int, sName nvarchar(50), GPA real, sizeHS int);
create table Apply(sID int, cName nvarchar(50), major nvarchar(50), decision text);
Inner join
内联接(Inner join)是最常用的联接范例之一,它查询满意联接谓词的数据.
假定我们要查询申请表Apply中申请学校的相关信息,由于Apply表中包含学校名字我们并不能预知,所以我们可以按照cName来内联接(Inner join)表College和Apply,从而找到Apply表中包含学校的信息.
具体SQL代码以下:
复制代码 代码以下:
---- Gets college information from college table
---- bases on college name.
SELECT DISTINCT College.cName, College.enrollment
FROM College INNER JOIN
Apply ON College.cName = Apply.cName
图1查询后果
cName | state | enrollment |
Stanford | CA | 15000 |
Berkeley | CA | 36000 |
MIT | MA | 10000 |
Cornell | NY | 21000 |
Harvard | MA | 29000 |
如上图1所示,我们把Apply表包含的学校信息查询出来了,由于Harvard并没有被查询出来,所以我们知道暂时还没有学生申请Harvard.
内联接(Inner join)满意交换律:"A inner join B" 和 "B inner join A" 是相等的.
Outer join
假定我们想看到全部学校信息;即便是那些没有申请的学校(如:Harvard),这时我们可以利用外部联接(Outer join)举行查询.由于外部联接保存一个或两个输入表的全部行,即便无法找到匹配联接谓词的行.
具体SQL代码以下:
复制代码 代码以下:
---- Gets all college information
SELECT College.cName, College.state, College.enrollment,
Apply.cName, Apply.major, Apply.decision
FROM College LEFT OUTER JOIN
图3左联接查询后果
如上图3所示:由于在Apply表中并没有学生申请Harvard,但是我们通过左联接(left outer join)把全部学校信息查询出来了.
由于左联接(left outer join)产生表College的完好集,而Apply表中匹配的则有值,而不匹配的则以NULL值代替,所以我们知道Apply表中没有学生申请Harvard.
通过左联接查询我们可以获得College的完好集,假定目前我们既要获得College的完好集又要获得Apply的完好集,那么我们可以考虑利用完好外部联接(full outer join).利用完好外部联接,我们可以查询全部的学校,不管它们能否匹配联接谓词:
复制代码 代码以下:
---- Gets all information from college and apply table.
SELECT College.cName, College.state, College.enrollment,
Apply.cName, Apply.major, Apply.decision
FROM College FULL OUTER JOIN
Apply ON College.cName = Apply.cName
图3 完好外部联接查询后果
目前我们获得了College和Apply的完好数据集,关于表中匹配的则有值,即便没有找到匹配cName的则以NULL值代替.
下表显示每种外部联接(outer join)匹配时保存数据行的情形:
联接范例 |
保存数据行 |
A left outer join B |
all A rows |
A right outer join B |
all B rows |
A full outer join B |
all A and B rows |
表2 外部联接保存数据行
完好外部联接(full outer join)满意交换律:"A full outer join B" 和 "B full outer join A" 是相等的.
Cross join
穿插联接(cross join)履行两个表的笛卡尔积(就是把表A和表B的数据举行一个N*M的组合).也就是说,它匹配一个表与另一个表中的每一行;我们不能通过利用ON子句在穿插联接指定谓词,固然我们可以利用WHERE子句来实现相同的后果,这是穿插联接基本上是作为一个内部联接了.
穿插联接相关于内部联接利用率较低,并且两个大表不该该举行穿插联接,因为这将招致一个非常高贵的操作和一个非常大的后果集.
具体SQL代码以下:
复制代码 代码以下:
---- College Cross join Apply.
SELECT College.cName, College.state, College.enrollment,
Apply.cName, Apply.major, Apply.decision
FROM College
CROSS JOIN Apply
图4 College表和Apply表的行数
图5 穿插联接
目前我们对College和Apply表举行穿插联接,并且生成数据行为College和Apply表行数的笛卡尔积即5 * 20 = 100.
Cross apply
在SQL Server 2005中供应了Cross apply使表可以和表值函数(table-valued functions TVF‘s)后果举行join查询.比方,目前我们想通过函数的后果值和表Student举行查询,这时我们可以利用Cross apply举行查询:
复制代码 代码以下:
---- Creates a function to get data from Apply base on sID.
CREATE FUNCTION dbo.fn_Apply(@sID int)
RETURNS @Apply TABLE (cName nvarchar(50), major nvarchar(50))
AS
BEGIN
INSERT @Apply SELECT cName, major FROM Apply where [sID] = @sID
RETURN
END
---- Student cross apply function fn_Apply.
SELECT Student.sName, Student.GPA, Student.sizeHS,
cName, major
FROM Student CROSS APPLY dbo.fn_Apply([sID])
我们也可以利用内部联接实现和Cross apply相同的查询功效,具体SQL代码以下:
复制代码 代码以下:
---- Student INNER JOIN Apply bases on sID.
SELECT Student.sName, Student.GPA, Student.sizeHS,
cName, major
FROM Student INNER JOIN [Apply]
ON Student.sID = [Apply].sID
图6 Cross apply查询
Outer apply
在介绍Cross apply和Outer join之后,目前让我们理解Out apply也就不难了,Outer apply使表可以和表值函数(table-valued functions TVF‘s)后果举行join查询,找到匹配值则有值,没有找到匹配值则以NULL表示.
复制代码 代码以下:
---- Student outer apply function fn_Apply.
SELECT Student.sName, Student.GPA, Student.sizeHS,
cName, major
FROM Student OUTER APPLY dbo.fn_Apply([sID])
图7 Outer apply查询
Inner Join和Cross apply的辨别
首先我们知道Inner join是表和表的联接查询,而Cross apply是表和表值函数的联接查询,在前面Cross apply例子中,我们也可以通过Inner join实现相同的查询.
复制代码 代码以下:
---- Student cross apply function fn_Apply.
SET STATISTICS PROFILE ON
SET STATISTICS TIME ON
SELECT Student.sName, Student.GPA, Student.sizeHS,
cName, major
FROM Student CROSS APPLY dbo.fn_Apply([sID])
SET STATISTICS PROFILE OFF
SET STATISTICS TIME OFF
---- Student INNER JOIN Apply base on sID.
SET STATISTICS PROFILE ON
SET STATISTICS TIME ON
SELECT Student.sName, Student.GPA, Student.sizeHS,
cName, major
FROM Student INNER JOIN [Apply]
ON Student.sID = [Apply].sID
SET STATISTICS PROFILE OFF
SET STATISTICS TIME OFFCross apply
查询履行时间:
CPU 时间= 0 毫秒,占用时间= 11 毫秒.
Inner join查询履行时间:
CPU 时间= 0 毫秒,占用时间= 4 毫秒.
图8 履行筹划
如图8所示:Cross apply首先履行TVF(table-valued functions),然后对表Studnet举行全表扫描,接着通过遍历sID查找匹配值.
Inner join对表Student和Apply举行全表扫描,然后通过哈希匹配查找匹配的sID值.
通过以上的SQL履行时间和履行筹划,我们能不能说Inner join比Cross apply好呢?答案能否定的,假如表的数据量很大,那么Inner join的全表扫描耗费时间和CPU资源就增添了(可通过数据量大的表举行测试).
固然大大都采取Cross apply实现的查询,可以通过Inner join实现,但Cross apply大概产生更好的履行筹划和更佳的性能,因为它可以在联接履行之前限制调集加入.
Semi-join和Anti-semi-join
Semi-join从一个表中返回的行与另一个表中数据行举行不完好联接查询(查找到匹配的数据行就返回,不再持续查找).
Anti-semi-join从一个表中返回的行与另一个表中数据行举行不完好联接查询,然后返回不匹配的数据.
差别于其他的联接运算,Semi-join和Anti-semi-join没有明确的语法来实现,但Semi-join和Anti-semi-join在SQL Server中有多种利用场所.我们可以利用EXISTS子来实现Semi-join查询,Not EXISTS来实现Anti-semi-join.目前让我们通过具体的例子阐明吧!
假定要求我们找出Apply和Student表中sID匹配的学生信息,这和前面的Inner join查询后果将一样,具体SQL代码以下:
复制代码 代码以下:
---- Student Semi-join Apply base on sID.
SELECT Student.sName, Student.GPA, Student.sizeHS
----[Apply].cName, [Apply].major
FROM Student
WHERE exists (
SELECT *
from [Apply]
where [Apply].sID = Student.sID
)
我们发现常用的EXISTS子句,本来是通过Left Semi Join实现的,所以说Semi-join在SQL Server中又很多利用场所.
图10 履行筹划
目前要求我们找出还没有申请学校的学生信息,这时我们立即反映可以利用NOT EXISTS子句来实现该查询,具体SQL代码以下:
复制代码 代码以下:
---- Gets student still not apply for school.
SELECT Student.sID, Student.sName, Student.GPA, Student.sizeHS
----[Apply].cName, [Apply].major
FROM Student
WHERE NOT EXISTS (
SELECT *
FROM [Apply]
WHERE [Apply].sID = Student.sID
)
其实,我们常用的NOT EXISTS子句的实现是通过Anti-semi-join,通过履行筹划我们发目前查找匹配sID时,SQL利用 Left Anti Semi Join举行查询.
图11 查询后果
图12 履行筹划
1.1.3 总结
本文介绍了SQL中常用了联接查询方法:Inner join、Outer join、Cross join和Cross apply的利用场所和特点.
以上是“SQL Join的一些总结(实例)[MSSQL防范]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |
评论内容只代表网友观点,与本站立场无关!
评论摘要(共 0 条,得分 0 分,平均 0 分)
查看完整评论