SQL Server 一些关键字详解(二)

1.LEFT JOIN 容易让人误解的地方

背景:因为在网上搜了下 LEFT JOIN 和 OUTER APPLY 的区别,时发现,有的网友解释为: 

  1) A   left  join  B  的连接的记录数与A表的记录数同.

  2) LEFT JOIN 左连接 -- 显示左表所有存在的记录 记录数=左表.

像这些说法都不对的.根据我测试得出的结论应该是:

  LEFT JOIN 返回结果数 >= 左表的记录数

网上有部分人的解释都漏了 大于(>) 的那部分,后我找了下感觉比较权威的答案:

W3School中的解释为:

  LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。

 

在百度百科解释为:

  left join是以A表的记录为基础的,A可以看成左表,B可以看成右表,left join是以左表为准的。换句话说,左表(A)的记录将会全部表示出来,而右表(B)只会显示符合搜索条件的记录(例子中为: A.aID = B.bID)B表记录不足的地方均为NULL

 

好像都没有明显的说到:当左表的数据,在右表匹配到多条记录的情况,这样就很容易让人误解.下面我做了个例子,

  比如有个类别表(Category)内容如下:

 

  还有个类别明细表(CategoryDetail)内容如下:

  那好现在测试开始:

  可以看到,本来左表(Category)里面只有三条数据的,使用了LEFT JOIN之后带出了四条数据,其中多出的就是对应左表(Category)匹配右表(CategoryDetail)数据时,出现多条数据的情况.

 

2.使用各种 JOIN 时需要注意的地方

  一般我们使用JOIN 时都是直接一个表名, ON 后面加条件如下:

 

  但是有时候也会这么写:

  这时候好像没什么问题,好的,要是再加个条件 把两个表关联起来,那么问题来了,假如我是这样写:

 

1 SELECT * FROM dbo.Category a
2 LEFT JOIN (SELECT * FROM dbo.CategoryDetail b WHERE b.Id=1 AND b.CategoryId=a.Id) AS c  ON 1=1

 

 

 

 

  这时候就就会很郁闷的发现报错了,报错如下:

  为什么会出现: 無法繫結多重部分(Multi-Part) 識別碼"a.Id" 错呢?我发现凡是适用JOIN时使用 括号() 然后在里面加select 语句时如果在使用外面的字段,就会报这个问题:

比如使用CROSS JOIN:

 

使用RIGHT JOIN:

 

使用INNER JOIN:

使用FULL JOIN:

  总结:使用JOIN关键字时,如果不是直接JOIN一个表名而是,使用圆括号() 里面加select 语句时,关联外部表字段时,就会出现無法繫結多重部分(Multi-Part) 識別碼 问题.

 

附注

 

附帶SQL腳本一份:

 

 

 

 1 /****** Object:  Table [dbo].[CategoryDetail]    Script Date: 08/19/2015 19:46:37 ******/
 2 SET ANSI_NULLS ON
 3 GO
 4 SET QUOTED_IDENTIFIER ON
 5 GO
 6 SET ANSI_PADDING ON
 7 GO
 8 CREATE TABLE [dbo].[CategoryDetail](
 9     [Id] [int] IDENTITY(1,1) NOT NULL,
10     [CategoryId] [int] NULL,
11     [Cry] [varchar](50) NULL,
12  CONSTRAINT [PK_CategoryDetail] PRIMARY KEY CLUSTERED 
13 (
14     [Id] ASC
15 )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
16 ) ON [PRIMARY]
17 GO
18 SET ANSI_PADDING OFF
19 GO
20 SET IDENTITY_INSERT [dbo].[CategoryDetail] ON
21 INSERT [dbo].[CategoryDetail] ([Id], [CategoryId], [Cry]) VALUES (1, 1, N'')
22 INSERT [dbo].[CategoryDetail] ([Id], [CategoryId], [Cry]) VALUES (2, 2, N'')
23 INSERT [dbo].[CategoryDetail] ([Id], [CategoryId], [Cry]) VALUES (3, 2, N'汪汪')
24 SET IDENTITY_INSERT [dbo].[CategoryDetail] OFF
25 /****** Object:  Table [dbo].[Category]    Script Date: 08/19/2015 19:46:36 ******/
26 SET ANSI_NULLS ON
27 GO
28 SET QUOTED_IDENTIFIER ON
29 GO
30 SET ANSI_PADDING ON
31 GO
32 CREATE TABLE [dbo].[Category](
33     [Id] [int] IDENTITY(1,1) NOT NULL,
34     [Name] [varchar](50) NULL,
35  CONSTRAINT [PK_Category] PRIMARY KEY CLUSTERED 
36 (
37     [Id] ASC
38 )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
39 ) ON [PRIMARY]
40 GO
41 SET ANSI_PADDING OFF
42 GO
43 SET IDENTITY_INSERT [dbo].[Category] ON
44 INSERT [dbo].[Category] ([Id], [Name]) VALUES (1, N'Cat')
45 INSERT [dbo].[Category] ([Id], [Name]) VALUES (2, N'Dog')
46 INSERT [dbo].[Category] ([Id], [Name]) VALUES (3, N'Tiger')
47 SET IDENTITY_INSERT [dbo].[Category] OFF
View Code

 

 

 

 

 

 

 

 

 

posted @ 2015-08-19 20:20  明Lam  阅读(3588)  评论(2编辑  收藏  举报