【问题标题】:Oracle sql queryOracle sql查询
【发布时间】:2015-07-17 10:13:56
【问题描述】:

我正在处理的表格(为了在此处显示)如下所示:

一个

A_ID         | Clob_Col   
1            | value        
2            | value   
3            | null   
4            | value   
5            | null  
6            | value   
7            | value   
8            | null  
9            | value   
10           | value    

B_ID          |A_ID          | C_ID  
10            | 1            | 20  
11            | 2            | 20  
12            | 6            | 21  
13            | 7            | 22  
14            | 8            | 22  
15            | 9            | 23  

C

C_ID       
20                  
21               
22               
23                    
24                   
25              

(所有表都有更多列)

我希望编写一个查询,该查询将返回所有三个表中的值,但排除某些值与表 C 中的值匹配的记录(不包含)。 我的问题是在表 C 上使用 NOT IN 子句时返回表 A 中 链接到表 B 的值。

例子:

SELECT a.A_ID, a.Clob_Col, b.B_ID, c.C_ID
from A a
LEFT JOIN B b on a.A_ID=b.A_ID
LEFT JOIN C c on b.C_ID=c.C_ID
WHERE a.AID >= 2
AND a.AID <= 7
AND c.C_ID NOT IN (22, 23, 24)

最后一行 - c.C_ID NOT IN (22, 23, 24) - 将在 B 表中留下以下记录:b_BID = 10,11 或 12

反过来,这些链接到表 A 中的以下记录:a.ID = 1,2 和 6。

第一个子句 - a.AID &gt;= 2 AND a.AID &lt;= 7 - 进一步将我们的最终结果限制为 a.ID = 2 和 6。 最终结果将如下所示:

A_ID         |Clob_Col         |B_ID          |C_ID         
2            |value            |11            |20                   
6            |value            |12            |21          

但是我还想返回未链接到表 B 的 A 表记录 - a.ID 3、4 和 5 所以我希望我的结果是

A_ID         |Clob_Col       |B_ID        |C_ID       
2            |value          |11          |20       
3            |null           |null        |null       
4            |value          |null        |null      
5            |null           |null        |null                 
6            |value          |12          |21           

注意:我包含 Clob 值的原因是有人建议选择所有记录,然后对 c.C_ID IN (22, 23, 24) 所在的记录执行 MINUS 操作。

这似乎是合理的,但是 Oracle 不允许涉及 Clob 列的 MINUS 操作。

【问题讨论】:

  • 只是一瞥,但您不需要在 JOIN 之后添加一些 ON 子句吗?
  • 这些数据的小提琴将是最有用的
  • 关于加入 c 表 - 如果 b 表中 a_id = 6 的 c_id 值不是 c_id 表中的值,您希望最终输出显示什么? a_id = 6 行是否显示? (简而言之,我问的是 c 表应该是内连接还是外连接到 b 表,如果是外连接,是否要将空值计为不在 (22,23,24) 中)
  • 感谢大家注意到缺少的 ON s。这是一个疏漏,已被纠正。但它并没有解决这个问题。

标签: sql oracle oracle-sqldeveloper


【解决方案1】:

我认为您忘记使用“on”子句进行连接。你可以试试这个:

SELECT a.A_ID, a.Clob_Col, b.B_ID, c.C_ID
from A a
LEFT JOIN B b on a.A_ID=b.A_ID
LEFT JOIN C c on b.C_ID=c.C_ID
WHERE a.A_ID between 2 and 7
AND c.C_ID NOT IN (22, 23, 24)

希望它会起作用。

【讨论】:

  • 再次感谢大家注意到缺少的 ON s。这是一个疏漏,已被纠正。但它并没有解决这个问题。
【解决方案2】:

包括您加入的内容,也可以将BETWEEN 用于第一个 WHERE 子句。

另外,我会根据您的数据使用 INNER JOINS 而不是 LEFT。

SELECT a.A_ID, a.Clob_Col, b.B_ID, c.C_ID
FROM A a
INNER JOIN B b ON a.A_ID = b.B_ID
INNER JOIN C c ON b.C_ID = c.C_ID
WHERE a.AID BETWEEN 2 AND 7
AND c.C_ID NOT IN (22, 23, 24)

【讨论】:

  • 未解决问题。仍然提供相同的结果
【解决方案3】:

我认为这可以满足您的需求:

with a as (select 1 a_id, 'val1' clob_col from dual union all
           select 2 a_id, 'val2' clob_col from dual union all
           select 3 a_id, null clob_col from dual union all
           select 4 a_id, 'val4' clob_col from dual union all
           select 5 a_id, null clob_col from dual union all
           select 6 a_id, 'val6' clob_col from dual union all
           select 7 a_id, 'val7' clob_col from dual union all
           select 8 a_id, null clob_col from dual union all
           select 9 a_id, 'val9' clob_col from dual union all
           select 10 a_id, 'val10' clob_col from dual),
     b as (select 10 b_id, 1 a_id, 20 c_id from dual union all
           select 11 b_id, 2 a_id, 20 c_id from dual union all
           select 12 b_id, 6 a_id, 21 c_id from dual union all
           select 13 b_id, 7 a_id, 22 c_id from dual union all
           select 14 b_id, 8 a_id, 22 c_id from dual union all
           select 15 b_id, 9 a_id, 23 c_id from dual),
     c as (select 20 c_id from dual union all
           select 21 c_id from dual union all
           select 22 c_id from dual union all
           select 23 c_id from dual union all
           select 24 c_id from dual union all
           select 25 c_id from dual)
select a.a_id, a.clob_col, b.b_id, c.c_id
from   a
       left outer join b on (a.a_id = b.a_id)
       left outer join c on (b.c_id = c.c_id)
where  a.a_id between 2 and 7
and    (c.c_id not in (22, 23, 24) or c.c_id is null)
order by a.a_id;

      A_ID CLOB_COL       B_ID       C_ID
---------- -------- ---------- ----------
         2 val2             11         20
         3                               
         4 val4                          
         5                               
         6 val6             12         21


and if c_id is 27 for a_id = 6 in the b table:

      A_ID CLOB_COL       B_ID       C_ID
---------- -------- ---------- ----------
         2 val2             11         20
         3                               
         4 val4                          
         5                               
         6 val6             12  

您必须考虑到 c_id 可能为空,以及不在被排除的值集中。

ETA:感谢 Ponder Stibbons 在 cmets 中的建议,如果您不希望在 a.a_id = b.a_id 匹配但 b.c_id = c.c_id 不匹配的位置显示该行,然后将 or c.c_id is null 更改为 or b.c_id is null 会删除该行:

with a as (select 1 a_id, 'val1' clob_col from dual union all
           select 2 a_id, 'val2' clob_col from dual union all
           select 3 a_id, null clob_col from dual union all
           select 4 a_id, 'val4' clob_col from dual union all
           select 5 a_id, null clob_col from dual union all
           select 6 a_id, 'val6' clob_col from dual union all
           select 7 a_id, 'val7' clob_col from dual union all
           select 8 a_id, null clob_col from dual union all
           select 9 a_id, 'val9' clob_col from dual union all
           select 10 a_id, 'val10' clob_col from dual),
     b as (select 10 b_id, 1 a_id, 20 c_id from dual union all
           select 11 b_id, 2 a_id, 20 c_id from dual union all
           select 12 b_id, 6 a_id, 27 c_id from dual union all
           select 13 b_id, 7 a_id, 22 c_id from dual union all
           select 14 b_id, 8 a_id, 22 c_id from dual union all
           select 15 b_id, 9 a_id, 23 c_id from dual),
     c as (select 20 c_id from dual union all
           select 21 c_id from dual union all
           select 22 c_id from dual union all
           select 23 c_id from dual union all
           select 24 c_id from dual union all
           select 25 c_id from dual)
select a.a_id, a.clob_col, b.b_id, c.c_id
from   a
       left outer join b on (a.a_id = b.a_id)
       left outer join c on (b.c_id = c.c_id)
where  a.a_id between 2 and 7
and    (c.c_id not in (22, 23, 24) or b.c_id is null)
order by a.a_id;

【讨论】:

  • 我认为这是最好的答案,唯一的事情是:我还想返回不链接到表 B 的 A 表记录。差别很小 - b.b_id is null 而不是 c.c_id is null - 如果我们插入到 B (16, 4, 55) 中它是可见的。
  • @PonderStibbons 我不确定我是否理解你 - (16, 4, 55) 是否意味着 A 基于 a_id = 4 链接到 B?我的查询给出了 (4, val4, 16, null) 的输出 - 你认为它应该返回什么?
  • @PonderStibbons 嗯,我明白你的意思 - 如果c.c_id = b.c_id 上没有匹配项,而a.b_id = b.b_id 时,OP 是否希望返回该行。我试图在我对这个问题的评论中澄清这一点,尽管我不确定我是否在上面说得足够清楚!
  • @PonderStibbons 用您的建议更新了我的答案 - 谢谢。如果您不希望显示该行,我对如何排除该行感到有些摸不着头脑!所有功劳都归功于你 *{:-)
  • 非常感谢您回答问题。很有魅力。
猜你喜欢
  • 2012-10-26
  • 2022-01-01
  • 2020-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-15
  • 2020-11-27
相关资源
最近更新 更多