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

问题描述 投票:0回答:2

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

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"等于其Num_B(第3行)(情况为“94000”)

所以新的列Comm_1将有Num_ANum_B的组合作为其值。同样适用于Comm_2

至于Comm_3,条件与Comm_1Comm_2相同,并且第1行Reg_1(或Reg_2)的'AAA'(或'CCC')等于第3行的Reg_1Reg_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

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

SELECT 
       IF(Num_B in (select distinct Num_A from mydata) , concat(Num_A,Num_B), Null) as Comm_1,
       IF(Num_C in (select distinct Num_A from mydata) , concat(Num_A,Num_C), Null) as Comm_2
FROM mydata

所以请提供任何提示并指出我阅读pl/sql中的正确点或我需要学习的程序。

sql oracle case
2个回答
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
投票

如果我正确理解逻辑,你可以使用这些子查询:

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以防万一匹配的行。

© www.soinside.com 2019 - 2024. All rights reserved.