2009-10-20 11 views
10

Mam dwa zaznaczenia i chcę je połączyć w taki sposób, aby zwracane były tylko wiersze unikalne w obu zaznaczeniach. Czy w Oracle 10g jest jakiś wbudowany sposób, aby to osiągnąć?Przeciwieństwem INTERSECT w Oracle

wiem, że mogę zrobić coś takiego:

 
(select1 UNION select2) 
MINUS 
(select1 INTERSECT select2) 

ale chciałbym tego uniknąć. Zarówno select1, jak i select2 mają 20 linii, więc ten sposób byłby naprawdę mało znany i trudny do utrzymania.

+1

Nazwa tego operatora jest „różnica symetryczna” - z tym, google daje liczbę wyników (Wich wszyscy wydają się sugerować, to nie będzie szybko). – AakashM

+0

Nie jest to dla mnie problemem, jeśli jest to powolne.Jest to skrypt wsadowy do mojego osobistego użytku, nie ma potrzeby, aby był super wydajny. –

+0

Jak wyglądają dwa wybory? Możliwa jest ich modyfikacja, dzięki czemu można uruchomić tylko jedno zaznaczenie i uzyskać ostateczny wynik. –

Odpowiedz

8

Jeśli oba select1 i select2 powrotne ma duplikatów, można użyć coś takiego:

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

Oto kolejny pomysł:

  • Do pełnego sprzężenia zewnętrznego z WYBIERZ1 i Select2
  • użytku tylko te rekordy z select1.id = NULL (rekord jest tylko w select2) lub select2.ID = NULL (rekord jest tylko w select1)

tak:

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 
    ) 
) 

zrobić to

1

Ten pracował dla mnie- nie wiem, jak szybko to jest.

(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

W Oracle 10g masz do dyspozycji wspólne wyrazy tabel.

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 
); 

Utrzymuje to twoje zapytania o zapytania, które są łatwe w utrzymaniu, a cel ostatecznego zapytania jest jasny.

Oczywiście, mając Oracle dodać operatora SYM_DIFFERENCE do SQL byłoby jeszcze lepiej, ale nie jestem wstrzymując oddech — nie są one jeszcze przekonał BOOLEAN typ danych byłoby dobrym pomysłem.

0

Oto kolejne rozwiązanie, tym razem przy użyciu funkcji count() analitycznej (Oracle 10 lub nowszej).

Zalety:

  • można określić, które kolumn EXTRASECT (na przykład KK1 KK2, w tym przykładzie).
  • możemy wybrać kolumny inne niż kluczowe (np. NK1, NK2 ... w przykładzie), których nie wymagamy do dopasowania.
  • Efektywny plan.
  • Podobny do przykładu PRZYŁĄCZU PEŁNEGO ZEWNĘTRZNEGO, ale nie otrzymujemy kolumn klucza jako oddzielnych pól wymagających dekodowania lub przypadku, aby je złożyć.

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;