Поиск каждого значения столбца A в столбце B в SQL Oracle - PullRequest
0 голосов
/ 16 апреля 2019

Допустим, у меня есть этот тип набора данных:

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_A и Num_B в качестве значения.То же самое относится к Comm_2

Что касается Comm_3, условие такое же, как Comm_1 или Comm_2, и дополнительное условие, что Reg_1 (или Reg_2) строки 1 'AAA' (или 'CCC') равно Reg_1 или Reg_2 строки 3 (что имеет место).

Я хочу построить запрос так, чтобы результат выглядел так:

    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 или о чем-либо другомпроцедура мне нужно выучить.

Ответы [ 2 ]

2 голосов
/ 16 апреля 2019

Вы можете получить то, что (я думаю), что вы хотите с внешними я присоединяется:

-- 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 голос
/ 16 апреля 2019

Если я правильно понял логику, вы можете использовать эти подзапросы:

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

демо

Я использовал min на случай, если было много подходящих строк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...