【问题标题】:Why isn't my condition in the ON clause working?为什么我在 ON 子句中的条件不起作用?
【发布时间】:2017-10-03 13:13:59
【问题描述】:

我有两个表,我只想将 ma​​in_sys 中 curr_flag = 1 到 integrated_sys 中的行保留下来。这些查询返回不同的行,我不知道为什么。

查询结果请参见 REXTESTER:http://rextester.com/YYR54058

QUERY 1 - curr_flag filter is in WHERE clause
select 
    * 
from 
    main_sys m
    left join integrated_sys i  on (m.master_id_sysa = i.master_id_sysa 
                                    or m.master_id_sysb = i.master_id_sysb)
where
    m.curr_flag = 1


QUERY 2 - curr_flag filter is in ON clause
select 
    * 
from 
    main_sys m
    left join integrated_sys i  on (   (
                                       m.master_id_sysa = i.master_id_sysa 
                                       or m.master_id_sysb = i.master_id_sysb
                                       ) 
                                   and m.curr_flag = 1
                                   )

表 A:ma​​in_sys 包含位置的历史记录。

| hist_id | master_id_sysA | master_id_sysB | loc_desc    | curr_flag | eff_start_dt | eff_end_dt |
|---------|----------------|----------------|-------------|-----------|--------------|------------|
| 14009   | 1234           | 1234           | Detroit, MI | 1         | 7/2/2017     | 1/1/9999   |
| 14010   | 1234           | 1234           | Detroit, MI | 0         | 1/6/2017     | 7/1/2017   |
| 14011   | 1234           | 1234           | Detroit, MI | 0         | 9/2/2016     | 1/5/2017   |
| 14012   | 1234           | 1234           | Detroit, MI | 0         | 7/23/2016    | 9/1/2016   |
| 14013   | 1234           | 1234           | Detroit, MI | 0         | 5/31/2015    | 7/22/2016  |
| 90088   | 6655           | 6655           | Dover, DE   | 1         | 6/2/2015     | 6/21/2015  |
| 90087   | 6655           | 6655           | Dover, DE   | 0         | 6/1/2015     | 6/1/2015   |
| 90086   | 6655           | 6655           | Dover, DE   | 0         | 5/31/2015    | 5/31/2015  |
| 14413   | 8877           | NULL           | NULL        | 1         | 9/2/2017     | 12/31/9999 |
| 14412   | 8877           | 877            | Austin, TX  | 0         | 8/3/2017     | 9/1/2017   |
| 14411   | 8877           | NULL           | NULL        | 0         | 6/19/2017    | 8/2/2017   |
| 14410   | 8877           | 877            | NULL        | 0         | 2/18/2017    | 6/18/2017  |
| 14409   | 8877           | 877            | Austin, TX  | 0         | 2/16/2017    | 2/17/2017  |
| 14145   | 9595           | 9595           | Boston, MA  | 1         | 9/9/2006     | 10/10/2014 |
| 39014   | 9987           | 9987           | Atlanta, GA | 1         | 6/5/2017     | 1/1/9999   |
| 39013   | 9987           | 9987           | Atlanta, GA | 0         | 11/1/2016    | 6/4/2017   |
| 39012   | 9987           | 9987           | Atlanta, GA | 0         | 9/23/2016    | 10/31/2016 |
| 39011   | 9987           | 9987           | Atlanta, GA | 0         | 7/6/2016     | 9/22/2016  |
| 39010   | 9987           | 9987           | Atlanta, GA | 0         | 1/6/2016     | 7/5/2016   |

表 B - integrated_sys 表有每个位置的当前记录。

| loc_name       | master_id_sysA | master_id_sysB |
|----------------|----------------|----------------|
| Detroit, MI    | 1234           | 1234           |
| Atlanta, GA    | 9987           | 9987           |
| Dover, DE      | 6655           | 6655           |
| Boston, MA     | NULL           | 9595           |
| Tempe, AZ      | NULL           | 55             |
| Seattle, OR    | NULL           | 95             |
| Des Moines, IO | NULL           | 1478           |
| Bismarck, SD   | NULL           | 1515           |

这个问题说明了情况,但我仍然不知道为什么 ON 子句查询返回 curr_flag 为 0 的行: Why and when a LEFT JOIN with condition in WHERE clause is not equivalent to the same LEFT JOIN in ON?

【问题讨论】:

    标签: sql postgresql left-join


    【解决方案1】:

    如果m.curr_flag = 1LEFT JOIN 条件的一部分,则它不用于从左表中选择行,而仅从右表中选择行。 LEFT JOIN 只需保留左表中的所有输入行,尽管 ON 后面有任何条件。因此,如果你需要过滤左表的数据,那么你应该在WHERE子句后面写这样的条件(你的第一个查询)。

    【讨论】:

      【解决方案2】:

      因为它们在逻辑上是不同的。

      查询 1 - 选择左表中 curr_flag = 1 的所有记录,当 ON() 子句为真时保留右表中的所有记录 -> m.master_id_sysa = i.master_id_sysa or m.master_id_sysb = i.master_id_sysb

      查询 2 - 选择左表中的所有记录,当ON() 子句为真时保留右表中的所有记录 -> (m.master_id_sysa = i.master_id_sysa or m.master_id_sysb = i.master_id_sysb) AND m.curr_flag = 1

      编辑:为了澄清——左连接的ON() 子句不过滤来自LEFT 表的记录,它只过滤RIGHT 表。

      【讨论】:

      • 你能解释一下你对 Qry 2 的意思 - “当 ON() 子句为真时,保留右表中的所有记录”?不应该只返回 curr_flag = 1 的行,还是 ON() 子句不限制结果集?
      猜你喜欢
      • 2017-11-10
      • 2013-01-09
      • 2011-12-20
      • 1970-01-01
      • 2013-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-21
      相关资源
      最近更新 更多