【问题标题】:left join not giving correct output左连接没有给出正确的输出
【发布时间】:2016-06-14 07:29:51
【问题描述】:

我有两张桌子

tableA

Accountid   
-----------  
10  
11  
12  

tableB

Accountid   |   Date        |   
--------------------------------------------    
10      |   2016-02-02  |   
11      |   2016-02-02  |   
11      |   2016-02-02  |    
15      |   2016-02-03  |   

我期待像

这样的输出
Accountid   |   ID  |   
------------------------------------    
10      |   10  |   
11      |   11  |   
12      |   NULL    |   

我正在运行这个查询

select A.accountid,b.accountid as ID 
from tableA as A 
left join tableB as B on a.accountid=b.accountid 
where b.date between '2016-02-02' and '2016-02-02'

但它给了我输出,我不确定我哪里出错了

Accountid   |   ID  |   
----------------------------------- 
10      |   10  |   
11      |   11  |   

我正在使用 MSSQL 数据库。

【问题讨论】:

  • b.date between '2016-02-02' and '2016-02-02' 移动到连接条件中。将其放入where 会将外连接变为内连接
  • 这是由于 b.date 在 '2016-02-02' 和 '2016-02-02' 之间......
  • @a_horse_with_no_name 它的 where 条件将 join 的含义从左转为内是不正确的。只有当他将 a.accountid=b.accountid 放在 where 子句中时,这才是正确的
  • @MtwStark:如果外部表上的条件使用不应为空的值,那么where 条件使查询的行为类似于内部联接。跨度>
  • @a_horse_with_no_name 我们不知道日期字段是否为 NOT NULL,首先执行连接条件,它可以检索带有或不带有可为空字段的任何行.. 您使用 WHERE 子句过滤的内容可能是与 INNER JOIN 的结果不同

标签: sql sql-server outer-join


【解决方案1】:

当左连接的右表的任何字段出现在WHERE 子句中时,此连接的行为类似于INNER JOIN

要获得预期结果,您的查询应该是这样的

select A.accountid,b.accountid as ID 
from tableA as A 
left join tableB as B on a.accountid=b.accountid and 
                         b.date between '2016-02-02' and '2016-02-02'

【讨论】:

  • 实际上,您的意思是“left 连接的right 表的任何字段”。
  • @JaydipJ 如果我在同一日期有 2 个帐户 ID 为 11 并且我只想显示 11 一次怎么办。我正在使用 distinct,但它不起作用
  • 如果您有相同的帐户 ID 和相同的日期,则 Distinct 必须有效,您在使用 Distinct 时遗漏了一些东西
  • @JaydipJ 将日期条件移动到 ON 子句是正确的,但它的 where 条件将连接的含义从左到内是不正确的。
【解决方案2】:

试试这个:

select A.accountid,b.accountid as ID 
from tableA as A left join tableB as B on a.accountid=b.accountid 
where b.date is null or b.date between '2016-02-02' and '2016-02-02'

原因是,对于 AccountID 12,b.date 实际上为 null(因为 tableB 中没有行)。因此,如果您允许查询中的日期为空,您只会获得该行的结果。

【讨论】:

  • 小心,如果b.date真的可以得到空值你会没有预期的结果,真正的解决方案是在“ON”子句中添加过滤器
【解决方案3】:

如果 b 不存在 (id = 12) 你的 where 子句返回 false 。 如果您想查看 id=12 的行,您必须在“ON”子句中包含您的测试(b.date 在 '2016-02-02' 和 '2016-02-02' 之间):

   select A.accountid,b.accountid as ID from tableA as A left join tableB as B 
on a.accountid=b.accountid and b.date between '2016-02-02' and '2016-02-02'

【讨论】:

    【解决方案4】:

    原因是因为你select的WHERE子句是在LEFT JOIN之后执行的

    所以,第一个 sql server 会按照你的预期提取数据,第 12-NULL 行,

    然后它将被您的 WHERE 子句过滤掉并从输出中删除

    您可以按照@JaydipJ 和@RémyBaron 的建议在 JOIN 条件下移动日期过滤器

    或以这种方式在 JOIN 之前过滤 tableB:

    select A.accountid,b.accountid as ID 
    from tableA as A 
    left join (
      select * 
      from tableB 
      where b.date between '2016-02-02' and '2016-02-02'
    ) as B on a.accountid=b.accountid 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-23
      • 2012-05-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多