Oracle SQL-选择性过滤导致笛卡尔

时间:2018-08-11 13:16:04

标签: sql oracle performance cartesian-product

Oracle 12.2

我有一条导致我出现问题的SQL语句。我正在从名为BURNDOWN的表中检索数据。如果用户是管理员,则可以查看所有数据。如果用户不是管理员,则根据某些加入条件,他们将只能看到自己的内容。 我遇到的问题是用户是ADMIN时,我不需要其他表…随后,JOIN条件不相关,因此Oracle决定对所有内容进行笛卡尔联接… 如何解决这个问题,以便用户是Admin,我只查看一个表,否则查看所有表并包括连接条件?

示例SQL是人为的示例,但它显示了问题所在。

Select 
BURNDOWN.NAME,
BURNDOWN.ADDRESS,
BURNDOWN.STATE
from BURNDOWN, FILTER_A, FILTER_B, FILTER_C
Where
(
  :ISAdmin = 1
  Or
  (
 BURNDOWN.x=FILTER_A.x and
FILTER_A.y=FILTER_B.y and
FILTER_B.z=FILTER_C.z and
FILTER_C.user = :ThisUser
 )
)

2 个答案:

答案 0 :(得分:1)

大概是您想要的:

select bd.*
from burndown bd
where :ISAdmin = 1 or
      (exists (select 1 from FILTER_A a where bd.x = a.x) or
       exists (select 1 from FILTER_B b where bd.y = b.y) or
       exists (select 1 from FILTER_C c where bd.z = c.z)
      );

答案 1 :(得分:1)

使用EXISTS来查看FILTER表中是否存在数据,而无需将其加入结果中。

select bd.*
from   burndown bd
where  ( :isadmin = 1 or
         exists ( select 1 
                  from   filter_a a
                  inner join  filter_b b on b.y = a.y
                  inner join  filter_c c on c.z = b.z
                  where  a.x = bd.x
                  and    c.user = :ThisUser )
       )