我有一个像这样工作的oracle查询:
SELECT *
FROM VW_REQUIRED r
JOIN VW_ACTUAL a ON a.person_id = r.person_id AND a.target_id = r.target_id
必需的是详细说明所有必需培训材料的视图,实际是详细说明最近拍摄的特定课程的视图。这些查询中的每一个本身都需要不到2秒的时间来生成10k到10万行。
我想做的是:
SELECT *
FROM VW_REQUIRED r
WHERE NOT EXISTS ( SELECT 1 FROM VW_ACTUAL a WHERE a.person_id = r.person_id AND a.target_id = r.target_id)
并且需要超过20秒(我没有让它完成,因为这显然太长了。
然后我决定做一些与众不同的事情,我将原来的JOIN作为左连接,这样它就会向我显示所有必需的训练,以及实际的训练,只有它存在。
这很有效,而且速度非常快。
但是我想要一份没有实际培训的课程清单(即我们需要开展培训并接受培训的人员......)
当我尝试类似
时SELECT *
FROM VW_REQUIRED r
LEFT JOIN VW_ACTUAL a ON a.person_id = r.person_id AND a.target_id = r.target_id
WHERE r.person_id = null
我没有回来。我不确定我是否可以过滤掉没有实际结果的行。通常情况下,我会使用WHERE NOT EXISTS
,但其上的效果非常慢(而且我不认为我可以在视图上放置索引......)
我设法做出了一些有效的改变,但看起来很糟糕,我确信这是一个更好的解决方案。
SELECT
who, where_from, mand, target_id, grace_period, date_taken
FROM (
SELECT
r.person_id who,
r.where_from where_from,
r.mand mand,
r.target_id target_id
r.grace_period grace_period,
nvl(a.date_taken, to_date('1980/01/01','yyyy/mm/dd')) date_taken
FROM VW_REQUIRED r
LEFT JOIN VW_ACTUAL a ON a.person_id = r.person_id AND a.target_id = r.target_id
)
WHERE date_taken = to_date('1980/01/01','yyyy/mm/dd')
答案 0 :(得分:3)
我认为你只混合了表名。你能改变最后的地方
吗? a.person_id is null
所以你的查询应该是这样的:
SELECT *
FROM VW_REQUIRED r
LEFT JOIN VW_ACTUAL a ON a.person_id = r.person_id AND a.target_id = r.target_id
WHERE a.person_id is null
或者也许是“老”的方式?
SELECT *
FROM
VW_REQUIRED r,
VW_ACTUAL a
WHERE r.person_id = a.person_id(+)
AND r.target_id = a.target_id(+)
AND a.person_id is null
答案 1 :(得分:0)
也许你的问题来自不存在的查询中的错误计划。
您能告诉我们此查询的计划吗?
SELECT *
FROM VW_REQUIRED r
WHERE NOT EXISTS ( SELECT 1 FROM VW_ACTUAL a WHERE a.person_id = r.person_id AND a.target_id = r.target_id)
尝试更改连接算法(/ + use_nl(a) /或/ + use_hash(a) /)。 我认为这是一个嵌套循环。也许你必须在这个例子中加入一个哈希联接,就像这样
SELECT *
FROM VW_REQUIRED r
WHERE NOT EXISTS ( SELECT /*+use_hash(a)*/ 1 FROM VW_ACTUAL a WHERE a.person_id = r.person_id AND a.target_id = r.target_id)