LEFT OUTER JOIN未按预期执行

时间:2014-02-20 21:58:51

标签: sql sql-server

QUERY#1

SELECT     
     dbo.CLIENT.CLIENT_ID, dbo.CLIENT.GOC, dbo.SALES_UW_REGION.SALES_UNDERWRITING
FROM         dbo.CLIENT LEFT OUTER JOIN
                      dbo.SALES_UW_REGION ON dbo.CLIENT.GOC = dbo.SALES_UW_REGION.GOC
WHERE     (dbo.CLIENT.CLIENT_ID = 23721)

CLIENT_ID, GOC, SALES_UNDERWRITING
23721   332 Underwriting
23721   332 Sales

我可以理解为什么这只返回一行,原因是尽管LEFT外连接确保两个CLIENT记录都返回,即使它们不匹配,FILTER也会在连接后应用,因此结果集只有一个行。

查询#2

SELECT     
     dbo.CLIENT.CLIENT_ID, dbo.CLIENT.GOC, dbo.SALES_UW_REGION.SALES_UNDERWRITING
FROM         dbo.CLIENT LEFT OUTER JOIN
                      dbo.SALES_UW_REGION ON dbo.CLIENT.GOC = dbo.SALES_UW_REGION.GOC                      
WHERE     (dbo.CLIENT.CLIENT_ID = 23721)
and SALES_UW_REGION.SALES_UNDERWRITING = 'Sales '

CLIENT_ID   GOC SALES_UNDERWRITING
23721   332 Sales

但是,如果我将'SALES'过滤器移动到JOIN子句,我很惊讶看到仍然返回一行。

查询#3

SELECT     
     dbo.CLIENT.CLIENT_ID, dbo.CLIENT.GOC, dbo.SALES_UW_REGION.SALES_UNDERWRITING
FROM         dbo.CLIENT LEFT OUTER JOIN
                      dbo.SALES_UW_REGION ON dbo.CLIENT.GOC = dbo.SALES_UW_REGION.GOC                      
                      and SALES_UW_REGION.SALES_UNDERWRITING = 'Sales '
WHERE     (dbo.CLIENT.CLIENT_ID = 23721)

CLIENT_ID   GOC SALES_UNDERWRITING
23721   332 Sales

我预计,因为它是JOIN子句的一部分而且连接是LEFT OUTER,所以我会得到2行。通常,如果涉及两个列的相等匹配的JOIN条件,一个来自LEFT表,另一个来自teh RIGHT表,则在LEFT OUTER JOIN中,LEFT表将返回NULL值,用于从中选择的值对。如果我们将RIGHT表中的值与文字匹配,为什么它应该是不同的?不应该返回LEFT表中的行吗?

伙计,我认为这是我失败的基本内容......

以下是重新创建我所需要的内容:

CREATE TABLE [dbo].[CLIENT](
    [CLIENT_ID] [bigint] NOT NULL,
    [GOC] [char](3) NULL
) 
go

CREATE TABLE [dbo].[SALES_UW_REGION](
    [GOC] [char](3) NOT NULL,
    [SALES_UNDERWRITING] [varchar](12) NULL
) 
go


INSERT INTO [dbo].[CLIENT]([CLIENT_ID], [GOC])
SELECT 23721, N'332'
go

INSERT INTO [dbo].[SALES_UW_REGION]([GOC], [SALES_UNDERWRITING])
SELECT N'332', N'Underwriting' UNION ALL
SELECT N'332', N'Sales'
go

3 个答案:

答案 0 :(得分:3)

CLIENT表格中有一行CLIENT_ID = 23721

您将继续加入另一个包含多个CLIENT_ID = 23721行的表(当您在第一个查询中加入条件时),但是当更改加入条件时,它会从{{1}中排除其中一行表格。

您正在从RIGHT表中获取所有记录,无论他们是否加入LEFT表中的记录,正如预期一样。

答案 1 :(得分:3)

我认为你的困惑涉及对第一个结果集的误解:

CLIENT_ID, GOC, SALES_UNDERWRITING
23721   332 Underwriting
23721   332 Sales

虽然此结果集中有两行,但结果仅表示Client表中一行的数据。连接条件允许Client表中的单行匹配Sales_UW_Region表中的两行,因此Client表中该行的数据在结果集中重复。首先只有一个客户端记录,证明只有一个Client_ID,但记录的数据显示两次:Sales_UW_Region中的每个匹配记录一次。

稍后,当您将and SALES_UW_REGION.SALES_UNDERWRITING = 'Sales '条件作为join ON子句的一部分包含在内时,Client表中的原始单个记录仅匹配Sales_UW_Region表中的一条记录。该行的数据不再需要重复,因此只返回一行。

答案 2 :(得分:0)

您的理解是正确的。如果过滤器在JOIN的ON子句中,则不会从第一个表中删除行。

我认为你需要在别处寻找你的问题......你真的想在你的'Sales '常数中留下一个尾随空格吗?

这是一个测试它的JSFiddle:http://sqlfiddle.com/#!2/bfe32/3/0