2017-10-03 9 views
0

私は2つのテーブルを持っていますが、その中には行だけを結合します。main_sysここで、curr_flag = 1〜integrated_sysです。これらのクエリは異なる行を返すため、私は理由を理解できません。クエリ結果FORON句の条件が正しく機能しないのはなぜですか?

SEE 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:main_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である行戻っている理由私はまだ知らない:m.curr_flag = 1が、その後LEFT JOIN条件の一部である場合Why and when a LEFT JOIN with condition in WHERE clause is not equivalent to the same LEFT JOIN in ON?

答えて

1

を左側の表から行を選択するのには使用されず、右側の表からのみ行が選択されます。 LEFT JOINONの後ろの条件にもかかわらず、左のテーブルからすべての入力行を保持するだけです。したがって、左テーブルのデータをフィルタリングする必要がある場合は、WHERE句(最初のクエリ)の後ろにそのような条件を記述する必要があります。

1

これらは論理的に異なるためです。

クエリ1 - >m.master_id_sysa = i.master_id_sysa or m.master_id_sysb = i.master_id_sysb

クエリ2 - - 維持、左のテーブルからすべてのレコードを選択しcurr_flag = 1、ON()句がtrueの場合、右の表からすべてのレコードを保持するには、左側のテーブルからすべてのレコードを選択します右のテーブルからすべてのレコードON()句が真である - >(m.master_id_sysa = i.master_id_sysa or m.master_id_sysb = i.master_id_sysb) AND m.curr_flag = 1

EDIT:明確化のために - 左のON()句はLEFTテーブルからレコードをフィルタリングしない参加する、それだけでRIGHTテーブルをフィルタリングします。

+0

Qry 2の意味を説明できますか?「ON()句がtrueのときに、すべてのレコードを適切なテーブルから保持しますか? curr_flag = 1が返される行だけでなく、ON()節が結果セットを制限しないか? – psrpsrpsr

+0

@psrpsrpsr編集を参照してください。 – sagi

関連する問題