【问题标题】:Oracle SQL How to execute the second condition only if the first one has not been accepted?Oracle SQL 只有在第一个条件未被接受的情况下如何执行第二个条件?
【发布时间】:2022-01-11 00:51:00
【问题描述】:

我希望有人可以帮助我。案例:

我有一张表 COMPANY_ACCESS 包含这些列:

ID NUMBER,
COMPANY_ID NUMBER,
AREA_ID NUMBER,
TEAM_ID NUMBER,
CAN_ACCESS BOOLEAN

我有我的查询(不起作用):

SELECT * 
FROM COMPANY_ACCESS ca
WHERE 
    ca.CAN_ACCESS = true
    AND ((ca.COMPANY_ID = ?1 AND ca.AREA_ID = ?2 AND ca.TEAM_ID = ?3)
         OR (ca.COMPANY_ID = ?1 AND ca.AREA_ID = ?2 AND ca.TEAM_ID IS NULL)
         OR (ca.COMPANY_ID = ?1 AND ca.AREA_ID IS NULL AND ca.TEAM_ID IS NULL))

我在这里的意图是什么。从更具体的访问(使用所有参数)到不太具体的访问。如果我在第一个条件下有一个寄存器:

(COMPANY_ID = ?1 AND AREA_ID = ?2 AND TEAM_ID = ?3)

我不需要检查其他的,只返回这个寄存器。如果我没有。我将在没有 TEAM_ID 的情况下进行检查(没有 TEAM_ID 的访问对 AREA_ID 内的所有团队都有效)。但是,如果我执行此查询,我会在第一个条件、第二个条件和第三个条件中收到寄​​存器。这不是我的本意。如果我在第一个条件(更具体)中找到一个,我不需要其他人只返回这个寄存器。如果我之前没有找到任何条件,我只会检查第二个和第三个条件。

有人可以帮我吗?

【问题讨论】:

  • 澄清一下,绑定变量是可选传入的吗?意思是,如果你只传入 company_id,它只会返回对公司的访问权限?还是将所有参数都传入,并且您想返回与任何条件匹配的所有内容?
  • 所有参数都被传递。使用所有这些参数,我将检查更具体到不太具体的@Nick

标签: sql oracle11g oracle10g


【解决方案1】:

从 Oracle 12 开始,您可以使用绑定变量过滤行,然后对结果集进行排序,以便您的首选行排在第一位,然后使用 FETCH FIRST ROW WITH TIES 过滤掉其他行:

SELECT * 
FROM   COMPANY_ACCESS ca
WHERE  ca.CAN_ACCESS = true
AND    ca.COMPANY_ID = ?
AND    (   (ca.AREA_ID = ? AND (ca.TEAM_ID = ? OR ca.TEAM_ID IS NULL))
        OR (ca.AREA_ID IS NULL AND ca.TEAM_ID IS NULL))
ORDER BY
       ca.AREA_ID NULLS LAST,
       ca.TEAM_ID NULLS LAST
FETCH FIRST ROW WITH TIES;

在早期版本中,您可以使用解析函数进行过滤:

SELECT *
FROM   (
  SELECT ca.*,
         RANK() OVER (
           ORDER BY ca.AREA_ID NULLS LAST, ca.TEAM_ID NULLS LAST
         ) AS rnk
  FROM   COMPANY_ACCESS ca
  WHERE  ca.CAN_ACCESS = true
  AND    ca.COMPANY_ID = ?
  AND    (   (ca.AREA_ID = ? AND (ca.TEAM_ID = ? OR ca.TEAM_ID IS NULL))
          OR (ca.AREA_ID IS NULL AND ca.TEAM_ID IS NULL))
)
WHERE  rnk = 1;

如果只有一个匹配行,那么您可以使用ROWNUM 来进行过滤:

SELECT *
FROM   (
  SELECT *
  FROM   COMPANY_ACCESS ca
  WHERE  ca.CAN_ACCESS = true
  AND    ca.COMPANY_ID = ?
  AND    (   (ca.AREA_ID = ? AND (ca.TEAM_ID = ? OR ca.TEAM_ID IS NULL))
          OR (ca.AREA_ID IS NULL AND ca.TEAM_ID IS NULL))
  ORDER BY
         ca.AREA_ID NULLS LAST,
         ca.TEAM_ID NULLS LAST
)
WHERE  ROWNUM = 1;

【讨论】:

  • 这很好用。我不知道这个命令 NULLS LAST。是否有一种方法可以用最终为 null 的寄存器对结果进行排序?
  • @LucasAlves 是的。
猜你喜欢
  • 1970-01-01
  • 2021-01-28
  • 2014-12-30
  • 2018-07-10
  • 2021-11-26
  • 2020-06-26
  • 1970-01-01
  • 2018-10-08
  • 1970-01-01
相关资源
最近更新 更多