Transact-SQLSQL Server自动把left join自动转化为inner join以及关联时的数据重复问题

Posted lonelyxmas

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Transact-SQLSQL Server自动把left join自动转化为inner join以及关联时的数据重复问题相关的知识,希望对你有一定的参考价值。

原文:【Transact-SQL】SQL Server自动把left join自动转化为inner join、以及关联时的数据重复问题

 

1、SQL Server自动把left join自动转化为inner join的问题:

 

下面的两个语句都是left join的,但是一个却转化成了 inner join

  1. drop table a,B
  2. go
  3. create table a(id int)
  4. insert into a
  5. select 1 union all
  6. select 2
  7. create table b(id int,xxx varchar(10))
  8. insert into b
  9. select 1,‘xxx‘ union all
  10. select 2,‘xx‘
  11. go
  12. --这个还是left join
  13. select *
  14. from a
  15. left join b
  16. on a.id = b.id and b.xxx = ‘xxx‘
  17. /*
  18. id id xxx
  19. 1 1 xxx
  20. 2 NULL NULL
  21. */
  22. select * --这个就是转化为inner join
  23. from a
  24. left join b
  25. on a.id = b.id
  26. where b.xxx = ‘xxx‘
  27. /*
  28. id id xxx
  29. 1 1 xxx
  30. */

 

下面的图是执行计划:

技术图片

 

2、下面的语句,运行后会出来几条记录呢? 

 

  1. select*
  2. from
  3. (
  4. select 1 as id
  5. )a
  6. left join
  7. (
  8. select 1 as id
  9. union all
  10. select 1
  11. )b
  12. on a.id = b.id
  13. left join
  14. (
  15. select 1 as id
  16. union all
  17. select 1
  18. )c
  19. on a.id = c.id


 之所以会想到这个问题,是因为发现最近写的报表总是运行结果不对,数字偏大,报表的逻辑要比上面的语句复杂,但问题是一样的。

 

首先,查询结果要求出来明细数据,由于表a关联了表b,虽然表a中没有重复记录,但是表b中有重复记录,导致表a的一条记录与表b的2条记录关联时,结果集会有2条,然后再把产生的结果集再与表c关联,这时由于c表中也有重复数据,那么最后的结果集就会是4条。

看上去和笛卡尔积一样2*2 = 4,但其实是由于表b和表c都有重复记录,导致关联以后出现大量的重复数据,这个问题在写SQL语句的时候,一定要非常注意。

 

如果来解决这个问题呢?

一般可以先单独对有重复数据表进行去重,或者group by并按照需求进行聚合计算,然后再进行关联,这样就不会导致数字偏大。

发布了416 篇原创文章 · 获赞 135 · 访问量 94万+

以上是关于Transact-SQLSQL Server自动把left join自动转化为inner join以及关联时的数据重复问题的主要内容,如果未能解决你的问题,请参考以下文章

如何修改sql server主键自动增长

SQL SERVER 维护计划,自动备份数据库任务失败

sql server 2008错误日志如何优化自动删除

Window Server 2019 配置篇- 在域中建立WSUS以实现自动更新

server2008r2经常蓝屏或者自动重启

sql server 每加一条数据实现自动加一,但怎么实现删除一条数据后自动减一