Нахождение нечетной строки между двумя таблицами в Oracle - PullRequest
0 голосов
/ 13 октября 2018

У меня есть две таблицы со следующей схемой

id, fruit

В Таблице A значения такие:

A01, Apple
A02, Orange
A03, Pineapple
A03, Pineapple
A05, Banana

В Таблице B значения такие:

A01, Apple
A02, Orange
A03, Pineapple
A04, Pineapple
A05, Banana

Как можно согласовать эти две таблицы, чтобы получить только повторяющуюся строку A03 в TableA?Как и при личном сравнении кортежей и возвращении нечетного кортежа.

Я пробовал минусовый запрос, как показано ниже:

Select * from TableA
minus
Select * from TableB

Но это не возвращает ожидаемый набор результатов.

Ответы [ 3 ]

0 голосов
/ 13 октября 2018

Много лет назад на AskTom Марко Стефанетти предложил следующий блестящий подход.Требуется, чтобы каждая таблица считывалась только один раз, и выполняется только одна сортировка.

Контекст является наиболее общим: запрос найдет строки, которые существуют в одной таблице, но не в другой, но - когдаразрешены дубликаты - ТАКЖЕ найдутся строки, которые существуют в обеих таблицах, но они имеют разное количество дубликатов.

Я создаю тестовые данные в предложении WITH;когда вы тестируете решение, вы можете удалить его и начать с последнего оператора SELECT.

with
  tablea (id, fruit) as (
    select 'A01', 'Apple'     from dual union all
    select 'A02', 'Orange'    from dual union all
    select 'A03', 'Pineapple' from dual union all
    select 'A03', 'Pineapple' from dual union all
    select 'A05', 'Banana'    from dual
  )
, tableb (id, fruit) as (
    select 'A01', 'Apple'     from dual union all
    select 'A02', 'Orange'    from dual union all
    select 'A03', 'Pineapple' from dual union all
    select 'A04', 'Pineapple' from dual union all
    select 'A05', 'Banana'    from dual
  )
select   id, fruit, count(case source when 'tablea' then 1 end) as count_in_a,
                    count(case source when 'tableb' then 1 end) as count_in_b
from     (
           select id, fruit, 'tablea' as source from tablea
           union all
           select id, fruit, 'tableb' as source from tableb
         )
group by id, fruit
having   count(case source when 'tablea' then 1 end) !=
         count(case source when 'tableb' then 1 end)
;

ID  FRUIT     COUNT_IN_A COUNT_IN_B
--- --------- ---------- ----------
A03 Pineapple          2          1
A04 Pineapple          0          1
0 голосов
/ 13 октября 2018

Похоже, что вы хотите исключить строки из A, присутствующие в B , и только точное их число .Я думаю, вы могли бы просто присвоить им номер строки:

SELECT "id", "fruit", ROW_NUMBER() OVER (PARTITION BY "id", "fruit" ORDER BY NULL) AS rn
FROM TableA
MINUS
SELECT "id", "fruit", ROW_NUMBER() OVER (PARTITION BY "id", "fruit" ORDER BY NULL) AS rn
FROM TableB

SQL Fiddle

0 голосов
/ 13 октября 2018

Это то, что вы хотите:

Select id, fruit
from TableA
group by id, fruit
having count(*) > 1
minus
Select id, fruit
from TableB;

Не ясно, действительно ли необходим tableB.Если у вас есть другие столбцы, которые вы хотите, вы можете выразить это с помощью exists:

Select id, fruit
from (select a.*, count(*) over (partition by id, fruit) as cnt
      from TableA a
     ) a
where cnt > 1 and
      exists (select 1 from tableB b where b.id = a.id and b.fruit = a.fruit);

или с помощью in:

Select id, fruit
from (select a.*, count(*) over (partition by id, fruit) as cnt
      from TableA a
     ) a
where cnt > 1 and
      (a.id, a.fruit) in (select b.id, b.fruit) from tableB);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...