Ответ 1
Если оба select1
и select2
не возвращают дубликатов, вы можете использовать что-то вроде этого:
SELECT * FROM (select1 UNION ALL select2) a
GROUP BY a.col1, a.col2, ...
HAVING count(*) = 1
У меня есть два выбора, и я хочу объединить их таким образом, чтобы возвращались только строки, уникальные в обоих select. Есть ли встроенный способ в Oracle 10g для этого?
Я знаю, что могу сделать что-то вроде этого:
(select1 UNION select2) MINUS (select1 INTERSECT select2)
но я хотел бы избежать этого. Оба select1
и select2
имеют 20 строк, поэтому этот способ будет действительно неясным и сложным в обслуживании.
Если оба select1
и select2
не возвращают дубликатов, вы можете использовать что-то вроде этого:
SELECT * FROM (select1 UNION ALL select2) a
GROUP BY a.col1, a.col2, ...
HAVING count(*) = 1
В 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
будет хорошей идеей.
Вот еще одна идея:
вот так:
SELECT *
FROM select1 FULL OUTER JOIN select2 on select1.id = select2.id
WHERE select1.id is null or select2.id is null
Это сработало для меня - не уверен, насколько это быстро.
(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')
-- get not intersect data
SELECT_FINAL
WHERE FIELD_PK IS NOT IN(
-- get ids of intersect
SELECT_AUX FIELD_PK1 FROM (
SELECT1
INTERSECT
SELECT2
)
)
Я делаю это
Здесь другое решение, на этот раз использующее аналитику count() (Oracle 10 или новее).
Преимущества:
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;