将ANSI 89的sql BETWEEN子句转换为ANSI 92

时间:2017-11-06 16:57:20

标签: sql oracle left-join ansi-sql

我正在尝试将ANSI 89中的sql语句转换为ANSI 92(意思是将"(+)"转换为" OUTHER JOIN")

以下是代码:

select a.*, p.price
from article a, prices p
where a.product_id = p.product_id(+)
and trunc(sysdate) + 1 between a.date_from and date_to
and trunc(sysdate) + 1 between p.date_from(+) and p.date_to(+);

我知道(+)在LEFT或RIGHT JOIN中引用,取决于放置它的位置,但我无法知道如何转换最后一行( and trunc(sysdate) + 1 between p.date_from(+) and p.date_to(+)

到现在为止,我做了下面的事情:

select a.*, p.price
from article a
left join prices p
on a.product_id = p.product_id
where trunc(sysdate) + 1 between a.date_from and date_to

但我不知道如何改变最后的条件。

有人可以帮帮忙吗?

谢谢,

1 个答案:

答案 0 :(得分:0)

我假设每个表都有一个date_from和一个date_to,并且您想要比较两个范围。在这种情况下,您在示例查询中保留了a.,因此我添加了它。如果那不是你的意思,当然可以自由调整......

所以显而易见的困难是,如果你添加

and trunc(sysdate) + 1 between p.date_from and p.date_to

where子句,然后任何“生成的NULL s”记录将被该条件错误处理。因此,您可以将其添加到外部连接条件

select a.*, p.price
  from           article a
       left join prices p
    on a.product_id = p.product_id
   and trunc(sysdate) + 1 between p.date_from and p.date_to
 where trunc(sysdate) + 1 between a.date_from and a.date_to

从语义上讲,这有点像黑客攻击,因为p上的日期范围检查可能不是真正一个连接条件;但是这会将“外部”语义应用于条件。另一个更明确的选择是

select a.*, p.price
  from           article a
       left join prices p
    on a.product_id = p.product_id
 where trunc(sysdate) + 1 between a.date_from and a.date_to
   and (trunc(sysdate) + 1 between p.date_from and p.date_to
        or p.product_id is null)

(您可以放弃or,然后只说between coalesce(p.date_from, trunc(sysdate)) and coalesce(p.date_to, trunc(sysdate)+2))或类似的内容,但这假设只有生成的NULL条记录才能NULL那些值 - 即没有prices记录在这些列中实际上有NULL。)