在SQL Oracle中搜索列B中列A的每个值

时间:2019-04-16 14:14:55

标签: sql oracle case

假设我有这种类型的数据集:

row     Num_A   Num_B    Num_C    Reg_1    Reg_2
------  -----   -----    -----    -----    -----
   1    9400    9500     9700     AAA      CCC
   2    9700    9400     9500     BBB      DDD
   3    9500    9400     9200     EEE      AAA
   4    9100    9300     9900     AAA      DDD

请考虑以下条件:

在第1行中,Num_B "95000"出现在Num_A(第3行)中,对应的Num_A(第1行)"94000"等于其{ {1}}(第3行)(“ 94000”就是这种情况)

因此,新列Num_B将具有Comm_1Num_A的组合作为其值。 Num_B

也是如此

对于Comm_2,条件与Comm_3Comm_1相同,另外一个条件是第1行的Comm_2(或Reg_1){ {1}}(或Reg_2)等于第3行的'AAA''CCC'(是这种情况)。

我想构造一个查询,以便结果看起来像这样:

Reg_1

我尝试了以下基本语法,但不起作用:

Reg_2

因此,请提供任何提示,让我了解 row Num_A Num_B Num_C Reg_1 Reg_2 Comm_1 Comm_2 Comm_3 ------ ----- ----- ----- ----- ----- ----- ----- ----- 1 9400 9500 9700 AAA CCC 94009500 94009700 94009500 2 9700 9400 9500 BBB DDD 97009400 97009500 NULL 3 9500 9400 9200 EEE AAA 95009400 NULL 95009400 4 9100 9300 9900 AAA DDD NULL NULL NULL 中的正确知识或我需要学习的任何程序。

2 个答案:

答案 0 :(得分:2)

您可以通过外部自连接获得想要的(我认为):

-- CTE for sample data, including row_num to maintain display order
with mydata (row_num, Num_A, Num_B, Num_C, Reg_1, Reg_2) as (
  select 1, 94000, 95000, 97000, 'AAA', 'CCC' from dual
  union all select 2, 97000, 94000, 95000, 'BBB', 'DDD' from dual
  union all select 3, 95000, 94000, 92000, 'EEE', 'AAA' from dual
  union all select 4, 91000, 93000, 99000, 'AAA', 'DDD' from dual
)
-- actual query
select m.*,
  case when m1.num_a is not null then m.num_a || m1.num_a end as comm_1,
  case when m2.num_a is not null then m.num_a || m2.num_a end as comm_2,
  case when m3.num_a is not null then m.num_a || m3.num_a end as comm_3
from mydata m
left join mydata m1 on m1.num_a = m.num_b
left join mydata m2 on m2.num_a = m.num_c
left join mydata m3 on m3.num_a = m.num_b and (m3.reg_1 = m.reg_2 or m3.reg_2 = m.reg_1)
order by m.row_num;

   ROW_NUM      NUM_A      NUM_B      NUM_C REG REG COMM_1     COMM_2     COMM_3    
---------- ---------- ---------- ---------- --- --- ---------- ---------- ----------
         1      94000      95000      97000 AAA CCC 9400095000 9400097000 9400095000
         2      97000      94000      95000 BBB DDD 9700094000 9700095000           
         3      95000      94000      92000 EEE AAA 9500094000            9500094000
         4      91000      93000      99000 AAA DDD                                 

(为了保持显示顺序不变,我留在了row_num中,否则将不使用它;我认为那实际上不是表中的一列。)

comm_1值基于与另一行的左连接,该行的num_a与该行的num_b相匹配。

comm_2值基于与另一行的左连接,该行的num_a与该行的num_c相匹配。

comm_3的值与comm_1相同,但还必须使其reg_1与另一行的reg_2相匹配,反之亦然。 但是,这会将第3行的值计算为9500094000,而不是问题中显示的94009500,但是不清楚哪一个是正确的。

如果任何外部联接的匹配项不止一个,这还将获得重复的行;样本数据不是这种情况,但需要提防。我不知道如果发生这种情况,您将如何处理。


您也可以使用单个外部联接并在列表达式中进行更多的逻辑/聚合:

select m.row_num, m.num_a, m.num_b, m.num_c, m.reg_1, m.reg_2,
  max(case when m1.num_a = m.num_b then m.num_a || m1.num_a end) as comm_1,
  max(case when m1.num_a = m.num_c then m.num_a || m1.num_a end) as comm_2,
  max(case when m1.num_a = m.num_b and (m1.reg_1 = m.reg_2 or m1.reg_2 = m.reg_1)
    then m.num_a || m1.num_a end) as comm_3
from mydata m
left join mydata m1 on (m1.num_a = m.num_b) or (m1.num_a = m.num_c)
group by m.row_num, m.num_a, m.num_b, m.num_c, m.reg_1, m.reg_2
order by m.row_num;

   ROW_NUM      NUM_A      NUM_B      NUM_C REG REG COMM_1     COMM_2     COMM_3    
---------- ---------- ---------- ---------- --- --- ---------- ---------- ----------
         1      94000      95000      97000 AAA CCC 9400095000 9400097000 9400095000
         2      97000      94000      95000 BBB DDD 9700094000 9700095000           
         3      95000      94000      92000 EEE AAA 9500094000            9500094000
         4      91000      93000      99000 AAA DDD                                 

答案 1 :(得分:1)

如果我正确理解逻辑,则可以使用以下子查询:

select row_, Num_A, Num_B, Num_C, Reg_1, Reg_2, 
       (select min(m.num_a||' '||m.num_b) from mydata where num_a = m.num_b ) comm_1,
       (select min(m.num_a||' '||m.num_c) from mydata where num_a = m.num_c ) comm_2,
       (select min(m.num_a||' '||m.num_b) from mydata 
         where num_a = m.num_b and (reg_2 = m.reg_1 or reg_1 = m.reg_2)) comm_3
  from mydata m

demo

如果有很多匹配的行,我会使用min