简体   繁体   中英

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.

For my SQL version, the select statement returns rows for all TRUE conditions.

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 . Ie you number the rows, giving the best match #1, the second best #2, etc. Then you only keep the rows ranked #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 .

As of Oracle 12c you can also use the FETCH clause:

  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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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