Oracle SQL-UNION ALL返回行,即使它们不存在

时间:2019-10-09 19:13:34

标签: sql oracle

我有以下查询,它将两个较小的查询合并:

flat_list=[item for sublist in l foo(item) for item in sublist]

如果查询返回一行,而查询2返回一行,那么我将有两行是这样的:

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)

我想要哪个输出。如果这两个查询之一不返回行(或者即使两个都不返回行),那么我将返回零行。这不是我想要的。我一直希望'type'和'some_id'返回 如果没有数据。因此,如果这两个查询都没有任何数据,我的预期结果将是:

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

我尝试用NOT EXISTS来使每个查询都具有UNION,但那样的话'type | somefield | some_id --------------------------------------------- Static 1 | | 1 Static 2 | | 1 '就需要是一些任意的硬编码值。我想要的是始终显示传递的绑定变量some_id

3 个答案:

答案 0 :(得分:1)

一种选择是选择带有NOT EXISTS header dummy 行,以确定是否返回它(是,如果表中的实际行不存在;否,如果行存在)。

看看示例:请看第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)。

答案 1 :(得分:1)

也许是这样的:

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

答案 2 :(得分:1)

为您的查询创建一个CTE,为另外2行添加另一个CTE,并使用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)