2012-04-17 2 views
1

У меня есть две таблицы, которые я в настоящее время присоединения трех полей:каскадных/условное JOIN в SQL

SELECT t1.A, t1.B, t1.C, t2.D 
    FROM t1, t2 
WHERE t1.A = t2.A 
    AND t1.B = t2.B 
    AND t1.C = t2.C 

Из-за путями моих работ данных, если объединение не совпадает с A/B/C, то я хочу присоединиться к A/B. Если это соединение не совпадает, я просто хочу присоединиться к A. Является ли этот тип каскадного соединения возможным в SQL-запросе (я использую Oracle 10g)? Или мне нужно обрабатывать это с помощью кода?

+1

Не уверен, но кажется, что вы желающие ЛЕВОЙ Внутреннее соединение. –

+0

Если в конечном итоге вы примете строки, которые присоединяются только к 'A', тогда все остальные строки будут эффективными, не так ли? Разве это не будет так же, как просто присоединиться к «А» с самого начала? – Ollie

+1

Я собираюсь повысить уровень детализации на основе доступности данных. Но вы можете быть правы, я должен взглянуть на второй взгляд. – Paul

ответ

2

Будет ли это работать для вас?

SELECT DISTINCT 
     t1.A, 
     t1.B, 
     t1.C, 
     t2.D 
    FROM t1, t2 
    WHERE (t1.A = t2.A 
      AND t1.B = t2.B 
      AND t1.C = t2.C) 
     OR (t1.A = t2.A 
      AND t1.B = t2.B) 
     OR (t1.A = t2.A); 

EDIT:

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

SELECT t1.A, 
      t1.B, 
      t1.C, 
      t2.D, 
      (CASE 
       WHEN t1.A = t2.A 
       AND t1.B = t2.B 
       AND t1.C = t2.C 
       THEN 'A/B/C' 
       WHEN t1.A = t2.A 
       AND t1.B = t2.B 
       THEN 'A/B' 
       WHEN t1.A = t2.A 
       THEN 'A' 
       ELSE 'None' 
      END) AS match_criteria 
    FROM t1, t2 
    WHERE t1.A = t2.A; 

В результирующем вы можете увидеть, что уровень соответствия строк, а затем использовать данные оттуда. Возможно, обернув этот запрос во внешний запрос, вы можете либо отбросить строки, которые вам не нужны, либо определить приоритеты тех, которые вы хотите.

Надеется, что это помогает ...

+1

Я думаю, что это работает. Позвольте мне проверить некоторые данные. – Paul

+0

Я думаю, что это вернет слишком много строк. Он вернет все строки, где t1.A = t2.A и t1.B <> t2.B, даже если существует строка, для которой t1.A = t2.A * AND * t1.B = t2.B. –

+0

@LarryLustig, что приемлемо в вопросе OP. Это были бы приемлемые строки, которые будут возвращены, но 'distinct' удаляет любые дублированные строки. 'если соединение не совпадает с A/B/C, то я хочу присоединиться к A/B. Если это соединение не совпадает, то я просто хочу присоединиться к A' – Ollie

0
SELECT t1.A, t1.B, t1.C, t2.D 
    FROM t1 
    LEFT JOIN t2 
    ON t1.A = t2.A AND t1.B = t2.B AND t1.C = t2.C 

Попробуйте и убедитесь, что вам нравятся результаты, если не использовать это (psedo.code):

insert into #temptable 
SELECT t1.A, t1.B, t1.C, t2.D 
    FROM t1, t2 
    WHERE t1.A = t2.A AND t1.B = t2.B AND t1.C = t2.C 

IF select count(*) from #temptable = 0 then 
insert into #temptable 
SELECT t1.A, t1.B, t1.C, t2.D 
    FROM t1, t2 
    WHERE t1.A = t2.A AND t1.B = t2.B 
end if; 


IF select count(*) from #temptable = 0 then 
insert into #temptable 
SELECT t1.A, t1.B, t1.C, t2.D 
    FROM t1, t2 
    WHERE t1.A = t2.A 
end if; 

select * from #temptable 
drop #temptable 
+0

LEFT JOIN не дает результат, который я ищу. Я не думаю, что код psuedo будет либо потому, что он предполагает, что ни одна из записей, сопоставленных с A/B/C, перед попыткой сопоставления на A/B или просто A. Может быть сценарий, когда некоторые записи соответствуют всем трем , но некоторые из них соответствуют только двум, а некоторые только соответствуют одному. – Paul

+0

Теперь я понимаю, чего вы хотите :) –

2

Вы можете сделать это UNIONing три запроса вместе и, в более двух общих запросах, за исключением строк, которые были возвращены в более конкретном запросе.

Как вы определяете, какие строки, чтобы исключить из более общих запросов зависит от формы ваших данных, но вы можете попробовать что-то вроде этого:

SELECT t1.A, t1.B, t1.C, t2.D 
    FROM t1, t2 
WHERE t1.A = t2.A AND t1.B = t2.B AND t1.C = t2.C 
UNION 
SELECT t1.A, t1.B, t1.C, t2.D 
    FROM t1, t2 
WHERE t1.A = t2.A AND t1.B = t2.B 
    AND NOT EXISTS (SELECT * FROM t2 WHERE t2.A = t1.A AND t2.B = t1.B AND t2.C = t1.C) 
UNION 
SELECT t1.A, t1.B, t1.C, t2.D 
    FROM t1, t2 
WHERE t1.A = t2.A 
    AND NOT EXISTS (SELECT * FROM t2 WHERE t2.A = t1.A AND t2.B = t1.B) 
+0

Это дает мне правильный результат, но стоит дороже ответа Олли (по крайней мере, для моих данных). – Paul

+0

Очевидно, вы знаете, что хотите, чем я. Но буквальное чтение вашего вопроса указывает на то, что ответ Олли вернет строки, которые вы не хотите в своем результирующем наборе. Для простого теста см. Мой комментарий под ответом Олли. –

+0

Я получаю такое же количество строк с обоими запросами. Но время работы составляет 49 секунд против 0,8 секунды. – Paul