场景我需要使用(+)外连接语法将现有查询转换为ANSI语法。 原因:其中一个JOINS需要一个OR操作数,而(+)运算符不允许这样操作,但允许使用LEFT OUTER JOIN。 (至少我认为这是正确的。)
查询目标:表D包含两个层次结构的名称,BB和Commercial。通过这些表的简单连接将返回19个位置及其各自的层次结构。如果有效,我需要查看具有适当层次结构的所有位置,否则为NULL值。
(+)语法查询 - 正常工作:
select a.userid, a.firstname, a.lastname, b.name PositionName, d.name Hierarchy
from cs_participant a, cs_position b, cs_positionrelation c, cs_positionrelationtype d
where a.payeeseq = b.payeeseq
and b.ruleelementownerseq = c.childpositionseq(+)
and c.positionrelationtypeseq = d.datatypeseq(+)
and b.removedate = to_date('01/01/2200','dd/mm/yyyy')
and b.effectiveenddate = to_date('01/01/2200','dd/mm/yyyy')
and c.removedate(+) = to_date('01/01/2200','dd/mm/yyyy')
and d.removedate(+) = to_date('01/01/2200','dd/mm/yyyy')
and a.removedate = to_date('01/01/2200','dd/mm/yyyy')
and a.effectiveenddate = to_date('01/01/2200','dd/mm/yyyy')
结果示例:
我尝试使用ANSI语法:
select a.firstname, a.lastname, b.name, d.name as "Hierarchy"
from cs_participant a, cs_position b
left outer join cs_positionrelation c on c.parentpositionseq = b.ruleelementownerseq
or c.childpositionseq = b.ruleelementownerseq (--This is the OR clause
that I cannot execute in the (+) syntax query)
left outer join cs_positionrelationtype d on d.datatypeseq = c.positionrelationtypeseq
where a.payeeseq = b.payeeseq
and b.removedate = to_date('01/01/2200','dd/mm/yyyy')
and b.effectiveenddate = to_date('01/01/2200','dd/mm/yyyy')
and a.removedate = to_date('01/01/2200','dd/mm/yyyy')
and c.removedate = to_date('01/01/2200','dd/mm/yyyy')
and c.effectiveenddate = to_date('01/01/2200','dd/mm/yyyy')
and d.removedate = to_date('01/01/2200','dd/mm/yyyy')
ANSI查询结果:
此查询仅返回分配给层次结构的位置。我需要查看所有位置,无论是否有层次结构分配,目前正从结果中排除。
答案 0 :(得分:2)
在第一个查询中,您有两个日期文字作为外部联接条件,但是您将它们留在第二个查询的where
子句中。要正确更改语法,需要将这些条件保留为连接条件的一部分。将两种连接语法(即在同一查询中使用逗号分隔表和join
关键字)组合起来也是一种不好的形式。
以下是第一个适合SQL-99语法的查询:
SELECT a.userid,
a.firstname,
a.lastname,
b.name AS positionname,
d.name AS hierarchy
FROM cs_participant a
JOIN cs_position b ON a.payeeseq = b.payeeseq
LEFT JOIN cs_positionrelation c
ON b.ruleelementownerseq = c.childpositionseq
AND c.removedate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
LEFT JOIN cs_positionrelationtype d
ON c.positionrelationtypeseq = d.datatypeseq
AND d.removedate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
WHERE b.removedate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
AND b.effectiveenddate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
AND a.removedate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
AND a.effectiveenddate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
一旦完成,将其调整为连接任一列都是微不足道的:
SELECT a.userid,
a.firstname,
a.lastname,
b.name AS positionname,
d.name AS hierarchy
FROM cs_participant a
JOIN cs_position b ON a.payeeseq = b.payeeseq
LEFT JOIN cs_positionrelation c
ON ( c.parentpositionseq = b.ruleelementownerseq
OR c.childpositionseq = b.ruleelementownerseq)
AND c.removedate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
LEFT JOIN cs_positionrelationtype d
ON c.positionrelationtypeseq = d.datatypeseq
AND d.removedate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
WHERE b.removedate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
AND b.effectiveenddate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
AND a.removedate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
AND a.effectiveenddate = TO_DATE ('01/01/2200', 'dd/mm/yyyy')
答案 1 :(得分:1)
(发布我的评论作为答案,以防这是你想要的)
OR与UNION相同。在oracle语法中,您可以执行
SELECT * FROM TABLE1, TABLE2 WHERE B1=C1(+)
union
SELECT * FROM TABLE1, TABLE2 WHERE B2=C2(+)
这与 -
相同SELECT * FROM TABLE1 LEFT JOIN TABLE2 ON (B1=C1 OR B2=C2)
(如果可能的话,也许可以使用UNION ALL)
Union是如何在oracle语法中实现FULL OUTER JOIN。
答案 2 :(得分:0)
问题是你的日期过滤器在where子句:
and d.removedate = to_date('01/01/2200','dd/mm/yyyy')
您需要将此条件移至表的join子句,或使用NVL处理空值(我假设您使用的是Oracle)。 试试这个例子:
select a.firstname,
a.lastname,
b.name as "PositionName",
d.name as "Hierarchy"
from cs_participant a
, cs_position b
left outer join cs_positionrelation c
on c.parentpositionseq = b.ruleelementownerseq
or c.childpositionseq = b.ruleelementownerseq
left outer join cs_positionrelationtype d
on d.datatypeseq = c.positionrelationtypeseq
and d.removedate = c.removedate --MOVED FROM WHERE
where a.payeeseq = b.payeeseq
and b.removedate = to_date('01/01/2200','dd/mm/yyyy')
and b.effectiveenddate = to_date('01/01/2200','dd/mm/yyyy')
and a.removedate = to_date('01/01/2200','dd/mm/yyyy')
and c.removedate = to_date('01/01/2200','dd/mm/yyyy')
and c.effectiveenddate = to_date('01/01/2200','dd/mm/yyyy');
或者只是在你的条件下添加NVL功能:
and nvl(d.removedate,to_date('01/01/2200','dd/mm/yyyy')) = to_date('01/01/2200','dd/mm/yyyy')