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