2009-10-20 2 views
10

У меня есть два выбора, и я хочу их объединить таким образом, чтобы возвращались только строки, уникальные в обоих select. Есть ли встроенный способ в Oracle 10g для достижения этого?Против INTERSECT в Oracle

Я знаю, что могу сделать что-то вроде этого:

 
(select1 UNION select2) 
MINUS 
(select1 INTERSECT select2) 

, но я хотел бы избежать. Оба select1 и select2 имеют 20 линий, поэтому этот способ будет действительно неясным и сложным в обслуживании.

+1

Имя этого оператора «симметрическая разность» - с этим, Google дает ряд результатов (которым все, как правило, предполагают, что это не будет быстро). – AakashM

+0

Это не проблема для меня, если это медленно.Это пакетный скрипт для моего личного использования, без необходимости его суперэффективности. –

+0

Как выглядят два выбора? Возможно, их можно будет изменить, так что вы запустите только один выбор и получите окончательный результат. –

ответ

8

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

SELECT * FROM (select1 UNION ALL select2) a 
GROUP BY a.col1, a.col2, ... 
HAVING count(*) = 1 
1

Вот еще одна идея:

  • ли полное внешнее объединение Выбор1 и выбор2
  • использования только те записи с select1.id = NULL (запись только в select2) или select2.ID = NULL (запись только в select1)

так:

SELECT * 
FROM select1 FULL OUTER JOIN select2 on select1.id = select2.id 
WHERE select1.id is null or select2.id is null 
0
-- get not intersect data 
SELECT_FINAL 
WHERE FIELD_PK IS NOT IN(
    -- get ids of intersect 
    SELECT_AUX FIELD_PK1 FROM (
     SELECT1 
     INTERSECT 
     SELECT2 
    ) 
) 

я сделать это

1

Это работает для меня-не знаю, как быстро это.

(select table_name from dba_tables where user = 'X' 
union 
select table_name from dba_tables where user = 'Y') 
minus 
(select table_name from dba_tables where user = 'X' 
intersect 
select table_name from dba_tables where user = 'Y') 
3

В Oracle 10g у вас есть общие табличные выражения в вашем распоряжении.

WITH 
    select_1 AS (
    SELECT * 
    FROM your_table 
    WHERE your_condition = 1 
), 
    select_2 AS (
    SELECT * 
    FROM your_other_table 
    WHERE your_other_condition = 1 
) 
SELECT * FROM select_1 
UNION 
SELECT * FROM select_2 
MINUS 
(
    SELECT * FROM select_1 
    INTERSECT 
    SELECT * FROM select_2 
); 

Это позволяет сохранить подзапросы в ремонте и очистить цель вашего окончательного запроса.

Конечно, имея Oracle добавить SYM_DIFFERENCE оператора SQL было бы еще лучше, но я не затаив дыхание — они все еще не убедили BOOLEAN тип данных будет хорошей идеей.

0

Вот еще одно решение, на этот раз использующее аналитику count() (Oracle 10 или новее).

Преимущества:

  • можно указать, какие столбцы EXTRASECT на (например, KK1 KK2 в примере).
  • В примере мы можем выбрать неключевые столбцы (например, NK1, NK2 ...), которые нам не нужны.
  • эффективный план.
  • Как и в случае с FULL OUTER JOIN, но мы не получаем ключевые столбцы как отдельные поля, требующие декодирования или корпуса, чтобы скомпоновать их.

select KK1, KK2, NK1, NK2 from (select KK1, KK2, NK1, NK2, count(*) over(partition by KK1, KK2) cnt from (select KK1, KK2, NK1, NK2 from X union all select KK1, KK2, NK1, NK2 from Y)) where cnt = 1;

Смежные вопросы