2016-05-16 83 views
0

提供了以下的结构和数据:SQL:加入两个表的/结合,在多个条件

CREATE TABLE "CHANGES" ( 
    "ID" NUMBER(38), 
    "LAST_UPD_DATE" DATE DEFAULT SYSDATE 
); 

CREATE TABLE "EXPORT_LOG" (
    "ID" NUMBER(38), 
    "LAST_EXPORT" DATE DEFAULT SYSDATE 
); 

CHANGES包含:

---------------------------- 
| ID | LAST_UPD_DATE  | 
---------------------------- 
| 123 | 12-MAY-16 12.23.23 | 
| 124 | 12-MAY-16 12.24.23 | 
| 125 | 12-MAY-16 12.11.23 | 
---------------------------- 

EXPORT_LOG

---------------------------- 
| ID | LAST_EXPORT  | 
---------------------------- 
| 124 | 12-MAY-16 12.23.12 | 
| 125 | 12-MAY-16 12.12.24 | 
---------------------------- 

我需要获取CHANGES中的记录,这些记录不存在于EXPORT_LOG或者,如果存在,则获得比LAST_EXPORTLAST_UPD_DATE的记录。 所以在上面的例子中,我应该得到123和124

我尝试不同的连接,但我似乎无法得到我想要的结果: INNER JOIN用于十字路口,LEFT JOIN获取所有第一表,但只有那些符合你设定条件的第二张表 - 这些都不是我想要的。那么解决方案是什么联盟?

回答

3

试试这个:

SELECT t1.* 
FROM CHANGES AS t1 
LEFT JOIN EXPORT_LOG AS t2 ON t1.ID = t2.ID 
WHERE (t2.ID IS NULL) OR (t1.LAST_UPD_DATE > t2.LAST_EXPORT) 

这将返回没有匹配CHANGES表中的所有记录EXPORT_LOGCHANGES记录有一个LAST_UPD_DATE晚于LAST_EXPORT

+0

谢谢,没有工作。但是,你能解释这是怎么回事吗?在'ON t1.ID = t2.ID'的结果之后是不是应用了where子句?因为没有'WHERE',没有记录't2.ID'为'null' – mavili

+1

@mavili - 是的,有。这正是外连接(在这种情况下为左连接)所做的 - 它创建了您正在讨论的记录,其中t1.id没有相应的t2.id。 (请注意,这并不意味着“t2.id为空” - 不确定你的意思。) – mathguy

0

一种方法是直接转换使用exists条件:

select c.* 
from changes c 
where not exists (select 1 from export_log el where c.id = el.id) or 
     not exists (select 1 from export_log el where c.id = el.id and el.last_export > c.last_upd_date); 

这可以简化为:

select c.* 
from changes c 
where not exists (select 1 from export_log el where c.id = el.id and el.last_export > c.last_upd_date); 
-1

请使用以下提到的代码,并提供我的意见。它应该按照您的要求工作。

SELECT CH.ID, CH.LAST_UPD_DATE 
 
FROM CHANGES CH, EXPORT_LOG EL 
 
WHERE CH.ID = EL.ID(+) 
 
AND ((EL.ID IS NULL) OR (CH.LAST_UPD_DATE > EL.LAST_EXPORT));

+1

Giorgios已经发布了这个解决方案,但有一点不同:他使用推荐的连接语法。在此查询中没有理由使用过时的Oracle专有语法来进行外部连接。这个缺点是出于两个原因,特别是对于第一个。 – mathguy