Oracle SQL查询

4

我正在处理表格,为了在此处显示,它们看起来像以下内容:

A

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

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              

所有表格都有更多的列。

我希望编写一个查询,它将从三个表中返回值,但排除与 Table C 中某些值相匹配的记录(NOT IN)。 我的问题是在使用 NOT IN 子句时从 Table A 返回不链接到 Table 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)

最后一行代码将使B表中只有b_BID = 10,11或12的记录保留下来。
这些记录与A表中的以下记录相对应:a.ID = 1,2和6。
第一个条件进一步限制了我们最终结果为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子句吗? - michael667
1
这些数据的一个示例将非常有用。 - Kritner
1
关于加入c表 - 如果b表中a_id = 6的c_id值不在c_id表中,您希望最终输出显示什么?a_id = 6行是否会被显示?(简而言之,我想问的是c表应该与b表进行内部连接还是外部连接,如果是外部连接,您是否希望将null计算为不在(22,23,24)中或不是)。 - Boneist
感谢大家注意到 ON s 缺失的问题。 这是一个疏漏已经得到了纠正。 不过这并没有回答问题。 - p45
3个回答

3
我认为您忘记在连接操作中使用“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。 这是一个遗漏,已经得到纠正。 但这并没有解决问题。 - p45

2

请在加入的内容中包含使用BETWEEN作为第一个WHERE子句。

此外,根据您的数据,我建议使用INNER JOIN而不是LEFT JOIN。

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)

不回答问题。仍然提供相同的结果。 - p45

1
我认为这个可以满足你的需求:

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可能为空,同时也不在被排除的值集合中。
注:感谢Ponder Stibbons在评论中的建议,如果您不想显示a.a_id = b.a_id匹配但b.c_id = c.c_id上没有匹配的行,则将或c.c_id为null更改为或b.c_id为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)中,它就会变得明显。 - Ponder Stibbons
@PonderStibbons,我不确定我理解你的意思 - (16, 4, 55) 是指A基于a_id = 4与B相连吗?我的查询输出为(4, val4, 16, null) - 你认为它应该返回什么? - Boneist
@PonderStibbons 嗯,我明白你的意思了 - 这取决于 OP 是否希望在 c.c_id = b.c_id 没有匹配时返回行,当 a.b_id = b.b_id 时。我试图在问题的评论中澄清这一点,尽管我不确定我在那里是否表达清楚了! - Boneist
@PonderStibbons用你的建议更新了我的答案 - 谢谢。如果你不想让那一行显示,我有点困惑该如何排除它!所有的功劳归功于你*{:-) - Boneist
非常感谢您回答所提出的问题。 非常有效。 - p45

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接