Oracle SQL - UNION ALL возвращает строки, даже если они не существуют - PullRequest
1 голос
/ 09 октября 2019

У меня есть следующий запрос, который объединяет два небольших запроса:

SELECT 'Static 1' type, somefield, some_id   
      FROM (SELECT some_id, somefield
               FROM sometable
                WHERE someothercolumn = 'Static 1'
                and someid = :id)
     UNION ALL
     SELECT 'Static 1' type, somefield, some_id   
      FROM (SELECT some_id, somefield
               FROM sometable
                WHERE someothercolumn = 'Static 2'
                and someid = :id)

Если запрос возвращает строку, а запрос 2 возвращает строку, то у меня будет две строки, подобные этой:

type      |      somefield     |     some_id
---------------------------------------------
Static 1  |       somevalue    |      1
Static 2  |       somevalue    |      1

Какой вывод я хочу. Если один из этих двух запросов не возвращает строку (или даже если оба не возвращают строку), тогда мне будет возвращено ноль строк. Это не то, что я хочу. Я всегда хочу, чтобы 'type' и 'some_id' возвращались, даже если данных нет. Поэтому, если бы оба этих запроса не имели данных, мой ожидаемый результат был бы:

type      |      somefield     |     some_id
---------------------------------------------
Static 1  |                    |      1
Static 2  |                    |      1

Я попытался ОБЪЕДИНИТЬ ВСЕ каждый запрос с НЕ СУЩЕСТВУЮЩИМ, но таким образом 'some_id' потребовалось быбыть произвольным жестко закодированным значением. Я хочу, чтобы он всегда показывал переданную переменную связывания, :id.

Ответы [ 3 ]

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

Возможно что-то вроде:

WITH a AS (/* subquery 1 */),
     b AS (/* subquery 2 */)
SELECT (SELECT a.col1 FROM a),
       (SELECT a.col2 FROM a),
       ...
       FROM dual
UNION ALL
SELECT (SELECT b.col1 FROM b),
       (SELECT b.col2 FROM b),
       ...
       FROM dual
1 голос
/ 09 октября 2019

Создайте CTE для вашего запроса и другой CTE для 2 дополнительных строк и используйте UNION ALL, а НЕ СУЩЕСТВУЕТ, как это:

WITH 
  cte1 AS (
    <your query here>
  ),
  cte2 AS (
    SELECT 'Static 1' type, null somefield, :id FROM dual
    UNION ALL
    SELECT 'Static 2' type, null somefield, :id FROM dual 
  )
SELECT * FROM cte1
UNION ALL
SELECT * FROM cte2
WHERE NOT EXISTS (SELECT 1 FROM cte1)
1 голос
/ 09 октября 2019

Один из вариантов - выбрать строку-заглушку заголовка с помощью NOT EXISTS, чтобы решить, следует ли ее возвращать (да, если фактическая строка в таблице не существует; нет, если строка существует).

Посмотрите на пример: посмотрите строку # 4, которая в настоящий момент закомментирована, что означает, что ваша таблица не содержит строки, удовлетворяющей этому условию, поэтому фиктивная строка header будетбудет отображаться:

SQL> with test (type, some_id) as
  2    (select 'Static 99', 44 from dual union all
  3     select 'Static 2' , 57 from dual
  4     --union all select 'Static 1', 66 from dual   -- toggle to see the difference
  5    )
  6  -- This is a header which won't be displayed if table contains
  7  -- type = 'Static 1' and some_id = 66
  8  select 'Static 1' type, 1 some_id
  9  from dual
 10  where not exists (select null
 11                    from test
 12                    where type = 'Static 1'
 13                      and some_id = 66
 14                   )
 15  union all
 16  -- This returns actual rows (if they exist)
 17  select 'Static 1' type, some_id
 18  from (select some_id
 19        from test
 20        where type = 'Static 1'
 21          and some_id = 66
 22       );

TYPE        SOME_ID
-------- ----------
Static 1          1

SQL>

Однако, если он существует (строка # 4 без комментариев), то отображаются фактические данные без этой строки заголовка-пустышки:

SQL> with test (type, some_id) as
  2    (select 'Static 99', 44 from dual union all
  3     select 'Static 2' , 57 from dual
  4     union all select 'Static 1', 66 from dual   -- toggle to see the difference
  5    )
  6  -- This is a header which won't be displayed if table contains
  7  -- type = 'Static 1' and some_id = 66
  8  select 'Static 1' type, 1 some_id
  9  from dual
 10  where not exists (select null
 11                    from test
 12                    where type = 'Static 1'
 13                      and some_id = 66
 14                   )
 15  union all
 16  -- This returns actual rows (if they exist)
 17  select 'Static 1' type, some_id
 18  from (select some_id
 19        from test
 20        where type = 'Static 1'
 21          and some_id = 66
 22       );

TYPE        SOME_ID
-------- ----------
Static 1         66

SQL>

Если это делает то, что выхотите, примените тот же принцип ко второму select, который вы используете (к Static 2).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...