简体   繁体   English

Oracle:是否可以根据列值选择要联接的表?

[英]Oracle: Is it possible to choose which table to join based on a column value?

First of all, this isn't my design, and I don't have the option of changing it. 首先,这不是我的设计,我没有选择更改它的选择。 I've got three tables that define a relationship between action items and incidents and audits. 我有三个表定义了行动项与事件和审计之间的关系。 The tables, in very simplified form, are set up like this: 这些表以非常简化的形式设置,如下所示:

ACTION_ITEMS
-------
ID    SOURCE_ID    SOURCE_TYPE
1     12345        INC
2     67890        AUD

INCIDENTS
-------
ID
12345

AUDITS
-------
ID
67890

The SOURCE_TYPE column indicates which of the other two tables is relevant to that row. SOURCE_TYPE列指示其他两个表中的哪一个与该行相关。 It's simple enough to get the details for all the records by creating separate queries for the incident and audit action items, joining those to the appropriate tables, and then performing a union. 通过为事件和审核操作项创建单独的查询,将这些查询联接到适当的表,然后执行联合,来获取所有记录的详细信息非常简单。

What I'd like to know is if it's possible to conditionally join to a table based on the value of a column. 我想知道的是,是否有可能基于列的值有条件地连接到表。 In other words, something like this, but that actually works: 换句话说,类似这样,但实际上有效:

SELECT
   AI.*
  ,INC.*
  ,AUD.*
FROM ACTION_ITEMS AI
JOIN
  CASE AI.SOURCE_TYPE
    WHEN 'INC' THEN INCIDENTS INC ON (AI.SOURCE_ID = INCIDENTS.ID)
    WHEN 'AUD' THEN AUDITS AUD ON (AI.SOURCE_ID = AUDITS.ID)
  END;

**Edited to clarify that I'm seeking to retrieve data from all tables. **编辑澄清我正在寻求从所有表中检索数据。

No, but you can join both tables and use the condition in your join clause: 否,但是您可以联接两个表并在join子句中使用条件:

SELECT AI.*
FROM ACTION_ITEMS AI
LEFT JOIN INCIDENTS ON AI.SOURCE_TYPE = 'INC' AND (AI.SOURCE_ID = INCIDENTS.ID)
LEFT JOIN AUDITS    ON AI.SOURCE_TYPE = 'AUD' AND (AI.SOURCE_ID = INCIDENTS.ID)

Note that you will be able to access columns from either table depending on the SOURCE_TYPE - if there's no match in the right-hand table those values will be NULL 请注意,您可以根据SOURCE_TYPE访问任一表中的列 - 如果右侧表中没有匹配项,则这些值将为NULL

You appear to be using the tables for filtering purposes, because you are not selecting from them. 您似乎正在使用表进行过滤,因为您没有从中进行选择。

Another way to write this is by using conditions in the where clause: 编写此内容的另一种方法是在where子句中使用条件:

select AI.*
from ACTION_ITEMS AI
where (AI.SOURCE_TYPE = 'INC' and
       exists (select 1 from INCIDENTS where AI.SOURCE_ID = INCIDENTS.ID)
      ) or
      (AI.SOURCE_TYPE = 'AUD' and
       exists (select 1 from AUDITS where AI.SOURCE_ID = AUDITS.ID)
      );

If you want to do this with join s, you have to use left outer join and then explicitly filter for matches: 如果要使用join s执行此操作,则必须使用left outer join ,然后显式过滤匹配:

SELECT AI.*
FROM ACTION_ITEMS AI LEFT JOIN
     INCIDENTS
     ON AI.SOURCE_ID = INCIDENTS.ID LEFT JOIN
     AUDITS
     ON AI.SOURCE_TYPE = 'AUD' AND (AI.SOURCE_ID = AUDITS.ID)
WHERE (AI.SOURCE_TYPE = 'INC' and INCIDENTS.ID is not null) OR
      (AI.SOURCE_TYPE = 'AUD' and AUDITS.ID is not null);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM