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 后面加条件如下:

  但是有时候也会这么写:

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

 SELECT * FROM dbo.Category a
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腳本一份:

 /****** Object:  Table [dbo].[CategoryDetail]    Script Date: 08/19/2015 19:46:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[CategoryDetail](
[Id] [int] IDENTITY(1,1) NOT NULL,
[CategoryId] [int] NULL,
[Cry] [varchar](50) NULL,
CONSTRAINT [PK_CategoryDetail] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
SET IDENTITY_INSERT [dbo].[CategoryDetail] ON
INSERT [dbo].[CategoryDetail] ([Id], [CategoryId], [Cry]) VALUES (1, 1, N'喵')
INSERT [dbo].[CategoryDetail] ([Id], [CategoryId], [Cry]) VALUES (2, 2, N'汪')
INSERT [dbo].[CategoryDetail] ([Id], [CategoryId], [Cry]) VALUES (3, 2, N'汪汪')
SET IDENTITY_INSERT [dbo].[CategoryDetail] OFF
/****** Object: Table [dbo].[Category] Script Date: 08/19/2015 19:46:36 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Category](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL,
CONSTRAINT [PK_Category] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
SET IDENTITY_INSERT [dbo].[Category] ON
INSERT [dbo].[Category] ([Id], [Name]) VALUES (1, N'Cat')
INSERT [dbo].[Category] ([Id], [Name]) VALUES (2, N'Dog')
INSERT [dbo].[Category] ([Id], [Name]) VALUES (3, N'Tiger')
SET IDENTITY_INSERT [dbo].[Category] OFF

SQL Server 一些关键字详解(二)的更多相关文章

  1. SQL Server 一些关键字详解(一)

    1.CROSS APPLY 和OUTER APPLY MSDN解释如下(个人理解不是很清晰): 使用 APPLY 运算符可以为实现查询操作的外部表表达式返回的每个行调用表值函数.表值函数作为右输入,外 ...

  2. MS SQL Server 数据库连接字符串详解

    MS SQL Server 数据库连接字符串详解 原地址:http://blog.csdn.net/jhhja/article/details/6096565 问题 : 超时时间已到.在从池中获取连接 ...

  3. SQL Server表分区详解

    原文:SQL Server表分区详解 什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在一个文件里. 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆 ...

  4. sql server 存储过程的详解

    SqlServer存储过程详解 1.创建存储过程的基本语法模板: if (exists (select * from sys.objects where name = 'pro_name')) dro ...

  5. SQL Server 性能优化详解

    故事开篇:你和你的团队经过不懈努力,终于使网站成功上线,刚开始时,注册用户较少,网站性能表现不错,但随着注册用户的增多,访问速度开始变慢,一些用户开始发来邮件表示抗议,事情变得越来越糟,为了留住用户, ...

  6. SQL server T-SQL索引详解

    SQL索引在数据库优化中占有一个非常大的比例,一个好的索引的设计,可以让sql语句查询效率提高很多被. 1.1 什么是索引? SQL索引有两种,聚集索引和非聚集索引,索引的主要目的是提高T-SQL系统 ...

  7. Sql Server之数据类型详解

      数据类型是一种属性,用于指定对象可保存的数据的类型,SQL Server中支持多种数据类型,包括字符类型.数值类型以及日期类型等.数据类型相当于一个容器,容器的大小决定了装的东西的多少,将数据分为 ...

  8. JDBC连接SQL Server 2005步骤详解

    一.设置SQL Server服务器:    1.“开始” → “程序” → “Microsoft SQL Server 2005” → “配置工具” → “SQL Server Configurati ...

  9. [转]MS SQL Server 数据库连接字符串详解

    http://blog.csdn.net/jackiehome/article/details/8668121 问题 : 超时时间已到.在从池中获取连接之前超时时间已过.出现这种情况可能是因为所有池连 ...

随机推荐

  1. JavaScript 变量克隆和判断变量类型

    一.变量克隆 在js中经常会遇到将一个变量赋值给一个新的变量这种情况,这对于基本类型很容易去实现,直接通过等号赋值就可以了,对于引用类型就不能这样了.(注:像函数,正则也可以直接通过等号赋值) 这里我 ...

  2. 构造一个简单的linux系统

    1.搭建环境 cd ~/Work/ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.6.tar.xz xz -d linux- ...

  3. 洛谷P1465

    P1465 序言页码 Preface Numbering 74通过 111提交 题目提供者该用户不存在 标签USACO 难度普及/提高- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 一类书 ...

  4. iOS地址编码解析

    - (void)viewDidLoad { [super viewDidLoad]; // 创建地址解析器 self.geocoder = [[CLGeocoder alloc] init]; } - ...

  5. wcscpy wcscpy_s strcpy strcpy_s的区别

    原型声明:extern char *strcpy(char *dest,const char *src); 头文件:string.h 功能:把从src地址开始且含有NULL结束符的字符串赋值到以des ...

  6. python jinjia2模板使用

    https://gist.github.com/wrunk/1317933 #!/usr/bin/env python # -*- coding: utf-8 -*- from jinja2 impo ...

  7. Ax Grid 的显示根据用户的需求动态排序。

    点击方向按钮上下移动记录. 设计思路. 以临时表TmpTable1举例. 在表中加一个real类型字段(eg:ColumnSeq)用于排序,给表建一个ColumnSeq字段的索引ColumnSeqId ...

  8. LoadRunner脚本 《第二篇》

    一.基础函数简介 在VU左边导航栏中,有三个LoadRunner框架函数,分别是vuser_init().Action().vuser_end().这三个函数存在于任何Vuser类型的脚本中. vus ...

  9. 你真的理解z-index吗?

    一.前言 假如只是开发简单的弹窗效果,懂得通过z-index来调整元素间的层叠关系就够了.但要将多个弹窗间层叠关系给处理好,那么充分理解z-index背后的原理及兼容性问题就是必要的知识储备了.本文作 ...

  10. 001MSP430概述

    1.MSP430系列单片机的特点 (1)超低功耗:生来就是为超低功耗设计的,从CPU内核结构到片上外设,以及整个芯片的生产制造都是本着超低功耗的原则来进行的,所以是一款实实在在的超低功耗单片机: (2 ...