SQL查询:如何使用一个查询检查多行的存在

时间:2016-07-29 18:20:51

标签: sql oracle

我有这张表MyTable

PROG    VALUE
-------------
1       aaaaa
1       bbbbb
2       ccccc
4       ddddd
4       eeeee

现在我正在检查是否存在具有某个id的元组,其查询类似于

SELECT COUNT(1) AS IT_EXISTS
FROM MyTable
WHERE ROWNUM = 1 AND PROG = {aProg}

例如我用aProg = 1获得

IT_EXISTS
---------
   1

我得到aProg = 3:

IT_EXISTS
---------
   0

问题是我必须进行多个查询,每个查询都要检查PROG的每个值。

我想要的是像

这样的查询
SELECT PROG, ??? AS IT_EXISTS
FROM MyTable
WHERE PROG IN {1, 2,3, 4, 5} AND {some other condition}

我可以得到像

这样的东西
PROG     IT_EXISTS
------------------
   1        1
   2        1
   3        0
   4        1
   5        0

数据库是Oracle ......

希望我明白

问候

4 个答案:

答案 0 :(得分:5)

退后一步,问问自己:你真的需要返回不存在的行来解决你的问题吗?我怀疑答案是否定的。您的应用程序逻辑可以确定未返回记录,这将允许您简化查询。

SELECT PROG
FROM MyTable
WHERE PROG IN (1, 2, 3, 4, 5)

如果您获得给定PROG值的行,则它存在。如果没有,它就不存在。

更新

在上述问题的评论中,您说:

  

prog值来自其他表。问题表只有所有prog值的子集

这告诉我一个简单的左外连接可以做到这一点。假设您感兴趣的PROG值的其他表名为MyOtherTable,则此类内容应该有效:

SELECT a.PROG,
CASE WHEN b.PROG IS NOT NULL THEN 1 ELSE 0 END AS IT_EXISTS
FROM MyOtherTable AS a
LEFT OUTER JOIN MyTable AS b ON b.PROG = a.PROG

如果您需要进一步过滤,可以在最后添加WHERE条款。

答案 1 :(得分:0)

我会推荐这样的东西。如果最多一行可以匹配表中的编程:

select p.prog,
       (case when t.prog is null then 0 else 1 end) as it_exists
from (select 1 as prog from dual union all
      select 2 as prog from dual union all
      select 3 as prog from dual union all
      select 4 as prog from dual union all
      select 5 as prog from dual
     ) p left join
     mytable t
     on p.prog = t.prog and <some conditions>;

如果可以匹配多行,您将要使用聚合来避免重复:

select p.prog,
       max(case when t.prog is null then 0 else 1 end) as it_exists
from (select 1 as prog from dual union all
      select 2 as prog from dual union all
      select 3 as prog from dual union all
      select 4 as prog from dual union all
      select 5 as prog from dual
     ) p left join
     mytable t
     on p.prog = t.prog and <some conditions>
group by p.prog
order by p.prog;

答案 2 :(得分:0)

一种解决方案是使用(可以说是滥用)hierarchical query来创建一个任意长的数字列表(在我的例子中,我将最大数字设置为最大值(PROG),但是你可以硬编码这个你知道你想要的顶级范围)。然后从该列表中选择并使用EXISTS检查它是否存在于MYTABLE中。

select
      PROG
    , case when exists (select 1 from MYTABLE where PROG = A.PROG) then 1 else 0 end IT_EXISTS
from (
    select level PROG
    from dual
    connect by level <= (select max(PROG) from MYTABLE) --Or hardcode, if you have a max range in mind
) A
;

答案 3 :(得分:0)

您仍然不太清楚要检查prog值的位置。但是,如果您可以从表中读取它们,并假设该表不包含重复的prog值,则这是我将使用的查询:

select a.prog, case when b.prog is null then 0 else 1 end as it_exists
  from prog_values_to_check a
  left join prog_values_to_check b
    on a.prog = b.prog
   and exists (select null
                 from MyTable t
                where t.prog = b.prog)

如果您确实需要对值进行硬编码,则可以通过利用SYS.DBMS_DEBUG_VC2COLL函数来完成此操作,该函数允许您将逗号分隔的值列表转换为行。

with prog_values_to_check(prog) as (
  select to_number(column_value) as prog
    from table(SYS.DBMS_DEBUG_VC2COLL(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) -- type your values here
)
select a.prog, case when b.prog is null then 0 else 1 end as it_exists
  from prog_values_to_check a
  left join prog_values_to_check b
    on a.prog = b.prog
   and exists (select null
                 from MyTable t
                where t.prog = b.prog)

注意:上述查询考虑到MyTable表可能有多个具有相同prog值的行,但您只需要在结果中有一行。我根据你问题中的WHERE ROWNUM = 1条件做出了这个假设。

相关问题