Условно откат к другому условию соединения, если более строгое условие не соответствует - PullRequest
0 голосов
/ 24 апреля 2019

У меня есть 2 таблицы j и c.

Обе таблицы имеют столбцы ports и sec, и JOIN ON j.ports = c.ports и c.sec = j.sec.

Для j.port = 'ABC', если для этих же портов нет c.sec = j.sec, тогда ПРИСОЕДИНЯЙТЕСЬ К ВКЛ. LEFT(c.sec, 6) = LEFT(j.sec, 6)

Для других j.ports я хочу присоединиться только к ВКЛ. j.ports = c.ports and c.sec = j.sec

Как я могу это сделать?

Пример данных

Таблица c

+------+------------+------------+
| Port |    sec     |   Other    |
+------+------------+------------+
| ABC  | abcdefghij |  ONE       |
| ABC  | klmnop     |  TWO       |
| LMN  | qwertyuiop |  THREE     |
| XYZ  | asdfghjkl  |  FOUR      |
+------+------------+------------+

Таблица j

+------+------------+
| Port |    sec     |
+------+------------+
| ABC  | abcdefxxxx |
| ABC  | klmnop     |
| LMN  | qwertyuiop |
| XYZ  | zxcvbnm    |
+------+------------+

РЕДАКТИРОВАНИЕ: Желаемые результаты

+------+------------+------------+
| Port |    sec     |  other     |
+------+------------+------------+
| ABC  | abcdefghij |  ONE       |  --> mactching on sec's 1st 6 characters 
| ABC  | klmnop     |  TWO       |  --> mactching on sec
| LMN  | qwertyuiop |  THREE     |  --> mactching on sec
+------+------------+------------+

Ответы [ 3 ]

0 голосов
/ 25 апреля 2019

Вы можете сделать два внешних соединения, а затем выполнить весь тип операции. В Oracle Nvl isnll из sqlserver

with c as 
(
    select 'ABC' port, 'abcdefghij' sec from dual
    union all select 'ABC', 'klmnop' from dual 
    union all select 'LMN', 'qwertyuiop' from dual
    union all select 'XYZ', 'asdfghjkl' from dual
),
j as 
(
    select 'ABC' port, 'abcdefxxxx' sec from dual
    union all select 'ABC', 'klmnop' from dual 
    union all select 'LMN', 'qwertyuiop' from dual
    union all select 'XYZ', 'zxcvbnm' from dual
)
select c.port, c.sec, nvl(j_full.sec, j_part.sec) j_sec
from c
     left outer join j j_full on j_full.port = c.port and j_full.sec = c.sec
     left outer join j j_part on j_part.port = c.port and substr(j_part.sec,1,6) = substr(c.sec,1,6)
order by 1,2

0 голосов
/ 26 апреля 2019

Один из способов - просто выполнить внутреннее объединение менее строгого предиката, а затем использовать функцию ранжирования для отбрасывания нежелательных строк в случае, если c.port = 'ABC' и более строгое условие соответствует определенному сочетанию c.port, c.sec.

with cte as
(
select c.port as cPort, 
       c.sec as cSec, 
       c.other as other,
       j.sec as jSec, 
       RANK() OVER (PARTITION BY c.port, c.sec ORDER BY CASE WHEN c.port = 'ABC' AND j.sec = c.sec THEN 0 ELSE 1 END) AS rnk
from c inner join  j on left(j.sec,6) = left(c.sec,6)
)
SELECT cPort, cSec, other, jSec
FROM cte 
WHERE rnk = 1
0 голосов
/ 25 апреля 2019

Это условное объединение:

select t1.*, t2.*
from j t1 inner join c t2
on t2.ports = t1.ports and
  case 
    when exists (select 1 from c where sec = t1.sec) then t1.sec 
    else left(t1.sec, 6) 
  end =
  case 
    when exists (select 1 from c where sec = t1.sec) then t2.sec 
    else left(t2.sec, 6) 
  end

Я ставлю под сомнение его эффективность, но думаю, что он делает то, что вам нужно.См. Демоверсию .

...