【问题标题】:Left join then inner join incorrect result using sql?使用sql的左连接然后内连接不正确结果?
【发布时间】:2017-03-20 06:58:19
【问题描述】:

我有 3 张桌子

drop table #temp;
create table #temp(id int,name varchar(50))

insert into #temp values(1,'ABC');
insert into #temp values(2,'XYZ');
select * from #temp

drop table #table_link;
create table #table_link(id int,temp_id int,temp2_id int)

insert into #table_link values(1,1,1);
insert into #table_link values(2,1,2);

select * from #table_link

drop table #temp2;
create table #temp2(id int,active_tag bit);
insert into #temp2 values(1,0)
insert into #temp2 values(2,1)

我想要的结果是使用#table_link 获取#temp 表和active_tag=1 中的所有行。

id  |  name | #temp2_id |
1   |  ABC  |  2        |
2   |  XYZ  |  NULL     |

我试过查询是

select * from #temp t
left join #table_link tl on tl.temp_id=t.id
inner join  #temp2 t2 on t2.id=tl.temp2_id and t2.active_tag=1 

在这个查询中,我只得到 ABC 行。我使用了左连接,为什么 XYZ 行没有得到。目前结果是这样的

id  |  name | #temp2_id |
1   |  ABC  |  2        |

请解释为什么它不起作用?

【问题讨论】:

标签: sql sql-server


【解决方案1】:

联接按其ON 子句存在的顺序“完成”。联接不只是在表之间——它们经常在其他联接产生的结果之间。所以:

select * from #temp t
left join #table_link tl on tl.temp_id=t.id
inner join  #temp2 t2 on t2.id=tl.temp2_id and t2.active_tag=1

首先在ttl 之间执行left join。这会产生一个新的结果集(我们称之为ttl),其中包含来自t 的行,并且可能包含来自tlnulls 的连接行(因为它是left join) .我们然后该结果 (ttl) 连接到t2,执行内部连接。但是,我们知道 ttl 可能包含来自 tl 的列的 nulls,因此 inner join 将失败。

我们可以改为:

select * from #temp t
left join #table_link tl
inner join #temp2 t2
 on t2.id=tl.temp2_id and t2.active_tag=1
 on tl.temp_id=t.id

请注意,我现在(通过移动on 子句)更改了连接的顺序。我们现在首先tlt2之间执行inner join(我们称之为t2tl)然后然后在@987654344之间执行left join @ 和 t2tl。这意味着left join 是最后起作用的,所以我们可以再次得到null 的结果作为最终结果。


要查看连接和on 子句的作用,请将join 单词视为(,将on 子句视为)。然后,您会找到与 on 子句相关的连接,即找到匹配的 ()s。

【讨论】:

    【解决方案2】:
    select t.id,t.Name,tl.temp2_id from #temp t
    left join #table_link tl on tl.temp_id=t.id
    AND EXISTS (SELECT 1 from #temp2 t2 WHERE t2.id=tl.temp2_id AND   t2.active_tag=1 )
    

    【讨论】:

    • 是的,谢谢。请解释为什么我的查询不正确?因为我在第二个表中使用了内部,所以第二个应该会来吗?
    • 因为你离开加入时就有了XYZ结果。但是,一旦您进行内连接,该记录就会被消除(这里的内连接将在前两个表的结果上执行)。
    【解决方案3】:

    试试这个:

     SELECT * 
     FROM #temp
     LEFT JOIN #table_link ON #table_link.id = #temp.id
     LEFT JOIN #temp2 ON #table_link.temp_id = #temp2.id
    

    您将获得所需的输出。您的查询中的问题可能是因为在以下位置加入了 #temp2: t2.id=tl.temp2_id

    【讨论】:

    • 这是我真实记录中的示例记录#table_link.temp_id = #temp2.​​id 是错误的。这是两个不同的表
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-15
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    • 1970-01-01
    相关资源
    最近更新 更多