SQL Union не включая дубликаты на основе одного столбца? - PullRequest
0 голосов
/ 09 октября 2019

Я пытаюсь объединить две таблицы, но мне нужно «предпочесть» первую таблицу, используя только один столбец «id». Если во второй таблице уже существует идентификатор, который уже существует в первой, я не хочу включать эту запись.

Запрос выглядит следующим образом

            select id, col2, col3
            from table(p_package.getData(param))

            union

            select id, col2, col3 
            from table1         
            where col7 = 'pass'
            and col8 <> 'A' 
            and col9 = to_date(Date, 'mm/dd/yyyy')

p_package.getData (param) - конвейерная функция, которая возвращает таблицу. Я хотел бы не называть это дважды из соображений производительности

Ответы [ 3 ]

1 голос
/ 09 октября 2019

Вы можете использовать аналитическую функцию ROW_NUMBER() для удаления дубликатов:

SELECT id, col2, col3
FROM   (
  SELECT id, col2, col3,
         ROW_NUMBER() OVER ( PARTITION BY id ORDER BY priority ) AS rn
  FROM   (
    select id, col2, col3, 1 AS priority
    from   table(p_package.getData(param))
  UNION ALL
    select id, col2, col3, 2
    from table1         
    where col7 = 'pass'
    and   col8 <> 'A' 
    and   col9 = to_date(Date, 'mm/dd/yyyy')
  )
)
WHERE rn = 1

и в качестве бонуса, поскольку вы фильтруете дубликаты в другом месте, вы можете изменить UNION наUNION ALL.

Если вы можете иметь дубликаты id значений из конвейерной функции и хотите, чтобы они были, но не любые из table1, тогда:

SELECT id, col2, col3
FROM   (
  SELECT id, col2, col3, priority
         ROW_NUMBER() OVER ( PARTITION BY id ORDER BY priority ) AS rn
  FROM   (
    select id, col2, col3, 1 AS priority
    from   table(p_package.getData(param))
  UNION ALL
    select id, col2, col3, 2
    from table1         
    where col7 = 'pass'
    and   col8 <> 'A' 
    and   col9 = to_date(Date, 'mm/dd/yyyy')
  )
)
WHERE priority = 1
OR    rn = 1
0 голосов
/ 09 октября 2019

Другие решения работают, но я решил использовать общее табличное выражение, предложенное xQbert

        with cte as
        (select id, col2, col3
        from table(p_package.getData(param)))

        select * from cte

        union

        select id, col2, col3 
        from table1         
        where col7 = 'pass'
        and col8 <> 'A' 
        and col9 = to_date(Date, 'mm/dd/yyyy')
        and id not in (select id from cte)

РЕДАКТИРОВАТЬ: я понял, что CTE на самом деле не хранит данные, возвращаемые запросом, но сохраняет запроссам по себе вместо. Несмотря на то, что это работает, не исключается двойной вызов конвейерной функции

0 голосов
/ 09 октября 2019

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

select col1, col2, col3
from table(p_package.getData(param))
union
select col1, col2, col3 
from table1 t1
where col7 = 'pass' and col8 <> 'A'and col9 = to_date(Date, 'mm/dd/yyyy') and
      not exists (select 1 from table(p_package.getData(param)) t2
                  where t1.col1 = t2.col1);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...