简体   繁体   English

SQL 仅在第一个 TRUE 条件下返回

[英]SQL returns only for 1st TRUE condition

I have a simple query which I want to return only one value in case first out of many condition is true.我有一个简单的查询,如果第一个条件为真,我只想返回一个值。

The query looks like this:查询如下所示:

SELECT * FROM table
WHERE case column 
           when val1 then 1
           when val2 then 1
           when val3 then 1
      end = 1

In table, can be rows for all values (val1, val2 and val3) but not mandatory and I want to return only 1st row for which the condition is true and waive the rest of the conditions.在表中,可以是所有值(val1、val2 和 val3)的行,但不是强制性的,我只想返回条件为真的第一行并放弃其余条件。

For my SQL version, the select statement returns rows for all TRUE conditions.对于我的 SQL 版本,select 语句返回所有 TRUE 条件的行。

Can you help me, please.你能帮我吗。

As I understand your request: There are different conditions on which you can find a match.据我了解您的要求:您可以根据不同的条件找到匹配项。 You only want to return the best matching row.您只想返回最匹配的行。

A typical example for this is a settings table that can contain settings for a country, city or even district.一个典型的例子是一个设置表,它可以包含一个国家、城市甚至地区的设置。 You'd want the district setting if available, else the city setting and only if this isn't available either will you content yourself with the global country setting.如果可用,您需要地区设置,否则需要城市设置,并且只有在此设置不可用时,您才会满足于全球国家/地区设置。

For such ranking you can use ROW_NUMBER .对于此类排名,您可以使用ROW_NUMBER Ie you number the rows, giving the best match #1, the second best #2, etc. Then you only keep the rows ranked #1.即您对行进行编号,给出最佳匹配#1、第二最佳#2,等等。然后您只保持排在#1 的行。

select *
from
(
  select
    s.*,
    row_number() 
      over (order by case
             when s.country = :country
              and s.city = :city
              and s.district = :district then 1
             when s.country = :country
              and s.city = :city then 2
             else 3
            end) as rn
  from settings s
  where s.country = :country
)
where rn = 1;

In your example:在你的例子中:

select *
from
(
  select 
    t.*,
    row_number()
      over (order by case column when val1 then 1 when val2 then 2 else 3 end) as rn
  from table t
  where column in (val1, val2, val3)
)
where rn = 1;

If there can be ties, ie if there is at least one row matching val1, then show all rows matching val1, etc., then use RANK or DENSE_RANK instead of ROW_NUMBER .如果可以有关系,即如果至少有一行与 val1 匹配,则显示所有与 val1 匹配的行,等等,然后使用RANKDENSE_RANK而不是ROW_NUMBER

As of Oracle 12c you can also use the FETCH clause:从 Oracle 12c 开始,您还可以使用FETCH子句:

  select *
  from table
  where column in (val1, val2, val3)
  order by row_number()
             over (order by case column when val1 then 1 when val2 then 2 else 3 end)
  fetch first row only;

Again, if you want to allow for ties, use RANK or DENSE_RANK and replace FETCH FIRST ROW ONLY with FETCH FIRST ROW WITH TIES .同样,如果您想允许DENSE_RANK ,请使用RANKDENSE_RANK并将FETCH FIRST ROW ONLY替换为FETCH FIRST ROW WITH TIES

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM