在第一个匹配条件之后是否有可能中断sql处理?

时间:2019-08-05 10:34:25

标签: sql oracle

假设我有一个包含以下记录的表

EmpTable::
Col1    Col2    Col3
1       John    Frank
2       Tom     Hank
3       Cathy   Hoogen
4       Dorothy Fran

我需要根据各种条件查找记录。仅当先前条件无法提供结果时,这些条件才需要进入下一个条件。

例如,如果我这样做

select * from EmpTable where Col3='Frank' OR Col3='Fran';

这将同时给我第1行和第4行。(如果在where子句中应用大小写,则结果相同)。 我希望sql要做的是在第一次匹配时停止,即当满足Col3 ='Frank'时停止进一步处理,在这种情况下,它将不返回通过匹配Col3 ='Fran'获得的结果。仅当第一个子句失败时,才应匹配Col3 ='Fran'并返回匹配的行。

我要匹配的条件很长,因此想知道是否有可能仅通过一个查询就可以有效地做到这一点?

我确实可以选择编写一个sql程序包,并对第一个子句进行存在性检查,并在存在时中断并返回结果集,然后使用不同的子句去运行下一个查询,依此类推。如果匹配,此程序包可能会返回1行或更多行。

非常感谢任何指针。

3 个答案:

答案 0 :(得分:1)

如果只需要一行,可以使用:

select *
from EmpTable
where Col3 in ('Frank', 'Fran')
order by (case when col3 = 'Frank' then 1 else 2 end)
fetch first 1 row only;

如果允许多个匹配项(或在旧版本的Oracle中),则可以使用窗口函数:

select e.*
from (select e.*,
             rank() over (order by (case when col3 = 'Frank' then 1 else 2 end)) as seqnum
      from EmpTable e
      where col3 in ('Frank', 'Fran')
     ) e
where seqnum = 1;

以上两个查询很容易将其概括为多个名称。您还可以将not existsunion all一起使用两个名称:

select e.*
from EmpTable e
where e.Col3 = 'Frank'
union all
select e.*
from EmpTable e
where e.Col3 = 'Fran' and
      not exists (select 1 from EmpTable e2 where e2.name = 'Frank');

答案 1 :(得分:1)

这里是一种通用方法,您只需编写一次每个条件,这将使此查询不太容易出错,因此非常易于维护。不过,这可能是以降低速度为代价的:-)

这个想法与戈登的前两个查询中的想法相同:对条件进行排名并选择排名最佳的比赛。

select *
from emptable
order by case
           when Col3 = 'Frank' then 1
           when Col3 = 'Fran' then 2
           when Col3 like 'Fr%' and col2 like 'J%' then 3
           when Col2 like 'J%' then 4
           ...
         end
  nulls last
fetch first row with ties;

答案 2 :(得分:0)

只需使用ROWNUM = 1:

select * from EmpTable where ROWNUM=1 AND (Col3='Frank' OR Col3='Fran');