【问题标题】:Oracle SQL - selective filtering causes cartesianOracle SQL - 选择性过滤导致笛卡尔
【发布时间】:2019-01-18 20:51:03
【问题描述】:

甲骨文 12.2

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

示例 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
 )
)

【问题讨论】:

  • 提示:从不FROM 子句中使用逗号。 始终使用正确、明确、标准JOIN语法。

标签: sql oracle performance cartesian-product


【解决方案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 )
       )

【讨论】:

  • 你确定这会起作用吗?我不知道 Oracle 是否实现了任何“捷径”布尔逻辑。
【解决方案2】:

大概,你想要:

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)
      );

【讨论】:

    猜你喜欢
    • 2017-11-27
    • 1970-01-01
    • 2020-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多