假设我有一个包含以下记录的表
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行或更多行。
非常感谢任何指针。
答案 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 exists
与union 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');