Oracle - 使用where子句的左外连接

时间:2016-09-10 04:51:50

标签: sql oracle join

我在两个表上定义为左外连接的连接,以便所有记录都从左手表返回,即使它们没有右表中的记录。但是我还需要包含一个where子句,但是......我还是希望左手表中的每一条记录都要返回一行,即使where子句中的条件不是't&t; t满足。有没有办法做到这一点?

我正在使用类似

的连接条件编写查询
SELECT A.*, B.* 
FROM A 
LEFT OUTER JOIN B ON A.VIN = B.VIN AND 
TRUNC(a.REP_OPEN_DATE) BETWEEN TRUNC(b.CHECK_IN_DATE)+1 AND TRUNC(b.CHECK_IN_DATE)-1

以上条件不返回任何行。以下条件返回...

SELECT A.*, B.* 
FROM A 
LEFT OUTER JOIN B ON A.VIN = B.VIN

我需要左表中的数据,即使以下条件不符合......

TRUNC(a.REP_OPEN_DATE) BETWEEN TRUNC(b.CHECK_IN_DATE)+1 AND TRUNC(b.CHECK_IN_DATE)-1

可以请一些人帮忙。

表: -

VIN    | RO_OPEN_DATE
1234   | 04-NOV-13
6789   | 09-NOV-13

B TABLE

VIN    | CHECK_IN_DATE
1234   | 09-NOV-13
1234   | 05-NOV-13
6789   | 20-OCT-14
6789   | 29-OCT-14

输出应该

   VIN     | RO_OPEN_DATE  | CHECK_IN_DATE
   1234    | 04-NOV-13     | 05-NOV-13
   6789    | 09-NOV-13     | NULL

Condition :-For EACH RO_OPEN_DATE for a VIN, We need to check if we have +/- 1 day of CHECK_IN_DATE from RO_OPEN_DATE.

2 个答案:

答案 0 :(得分:2)

您的解释与您的查询无关。你提到了

但是我还需要包含一个where子句但是......我仍然希望左手表中的每一行都返回一行,即使条件是不符合where子句。

所以我相信你的查询看起来像这样

SELECT a.*, 
       b.* 
FROM   a 
       LEFT OUTER JOIN b 
                    ON a.vin = b.vin 
WHERE  Trunc(a.rep_open_date) BETWEEN Trunc(b.check_in_date) + 1 AND 
                                      Trunc(b.check_in_date) - 1 

在上文中,由于LEFT OUTER JOIN子句中右表的过滤,INNER JOIN将转换为Where

因此,在第一次查询中使用时,正确的表过滤器应该是JOIN条件的一部分,即使右侧表中没有匹配的记录,它也将从LEFT表返回行。

SELECT a.*, 
       b.* 
FROM   a 
       left outer join b 
                    ON a.vin = b.vin 
                       AND Trunc(a.rep_open_date) BETWEEN 
                           Trunc(b.check_in_date) + 1 AND 
                           Trunc(b.check_in_date) - 1 

更新:

您在10 between 11 and 9之类的运算符之间使用了它,但它应该是10 between 9 and 11

SELECT a.*, 
       b.* 
FROM   a 
       left outer join b 
                    ON a.vin = b.vin 
                       AND CAST(a.rep_open_date as date) BETWEEN 
                           CAST(b.check_in_date as date) - 1 AND 
                           CAST(b.check_in_date as date) + 1 

答案 1 :(得分:0)

如果B中没有满足连接的行,那么您必须指定如何处理b.CHECK_IN_DATE的NULL值,例如,

TRUNC(a.REP_OPEN_DATE) BETWEEN TRUNC(NVL(b.CHECK_IN_DATE,a.rep_open_date))+1 AND TRUNC(NVL(b.CHECK_IN_DATE,a.rep_open_date))-1

当b.CHECK_IN_DATE为NULL时,您需要决定做什么,只要B中没有满足连接条件的记录就会发生这种情况,因为a.REP_OPEN_DATE永远不会在两个NULL之间。我使用a.rep_open_date作为一个总能成功的例子。您也可以简单地将OR b.checkin_date_date IS NULL添加到WHERE子句中。