始终 return 所有行,即使查询没有结果

Always return all row, even when query has no result

我有一个“tt_Results”table,它恰好包含三行/ID,例如:

ID | ResultType
---------------
1  |  first
1  |  second
1  |  third

我的查询如下:

select t.resultType
from tt_Results 
where ID = 1;

通常,此查询应该return 所有三行。我的问题是,如果一行或多行不存在,我必须合并所有三个“类型”。

 select res.* from
(
 select resultType, '1' as exists 
 from tt_Results 
 where ID = 1

 union all  

 select 'first' resulttype, '0' as exists
 from dual
 where not exists (
   select resulttype
   from tt_Results 
   where resulttype = 'first' and ID = 1)

 union all

 select 'second' resulttype, '0' as exists
 from dual
 where not exists (
   select resulttype
   from tt_Results 
   where resulttype = 'second' and ID = 1)

 union all

 select 'third' resulttype, '0' as exists
 from dual
 where not exists (
   select resulttype
   from tt_Results 
   where resulttype = 'third' and ID = 1)
) res

最终的查询结果看起来不错,但是速度很慢。有人有更好的 PL/SQL 解决方案吗?感谢您的回答!

您可以通过创建子查询来保存您感兴趣的结果类型,然后使用分区外部联接来实现此目的,如下所示:

with tt_results as (select 1 id, 'first' resulttype from dual union all
                    select 1 id, 'second' resulttype from dual union all
                    select 1 id, 'third' resulttype from dual union all
                    select 2 id, 'second' resulttype from dual union all
                    select 2 id, 'third' resulttype from dual union all
                    select 3 id, 'first' resulttype from dual),
          dummy as (select 1 position, 'first' resulttype from dual union all
                    select 2 position, 'second' resulttype from dual union all
                    select 3 position, 'third' resulttype from dual)
select res.id,
       d.resulttype,
       case when res.resulttype is not null then 1 else 0 end res_exists
from   dummy d
       left outer join tt_results res partition by (res.id) on d.resulttype = res.resulttype
order by res.id,
         d.position;

        ID RESULTTYPE RES_EXISTS
---------- ---------- ----------
         1 first               1
         1 second              1
         1 third               1
         2 first               0
         2 second              1
         2 third               1
         3 first               1
         3 second              0
         3 third               0

A​​drian Billington 在 partititioned outer joins 上发表了一篇精彩的文章,如果您想了解更多关于它们的信息。

如果您的 tt_results table 可能包含比您感兴趣的更多的结果类型,您可以 want/need 添加一个谓词以仅从虚拟子查询中获取行,否则您可以获得所有 3 个结果类型都不存在的 ID(尽管这可能是您想要看到的)。


预计到达时间:如果您需要一次性 select 多个 ID,这将有效。

从所有类型的 table 左连接到您的 table,使用 case 根据是否进行连接来计算 exists

select
    type,
    case when resultType is null then '0' else '1' end as exists
from (select 'first' type from dual union 
      select 'second' from dual union 
      select 'third' from dual) t
left join tt_Results on resultType = type
    and ID = 1

注意条件ID = 1join条件的一部分,notwhere子句中.


我建议为类型创建一个 3 行 table,这样查询将变得简单:

select
    type,
    case when resultType is null then '0' else '1' end as exists
from types
left join tt_Results on resultType = type
    and ID = 1