PGSQL — Объединение многих И ИЛИ в предложении WHERE

#sql #postgresql

Вопрос:

У меня есть такой формат таблицы:

 | productid | price          |
| ----------| -------------- |
| 1         | 10             |
| 2         | 20             |
| 3         | 30             |
| 4         | 40             |

 

Допустим, я хочу выбрать все строки, в которых:
(productid равен 1, а цена превышает 50) ИЛИ
(productid равен 2, а цена превышает 100) ИЛИ
(productid равен 3, а цена превышает 20)

Есть ли лучший универсальный способ достичь этого (что-то вроде массивов с индексами или что-то в этом роде), кроме того, чтобы делать по одному, например:

 select * from table where (productid = 1 and price > 50) OR
                          (productid = 2 and price > 100) OR
                          (productid = 3 and price > 20)

 

Ответ №1:

Я бы использовал предложение values:

 select * 
from the_table t
  join ( 
     values (1, 50), 
            (2, 100), 
            (3, 20)
  ) as p(productid, price) 
    on t.productid = p.productid 
   and t.price > p.price;
 

Комментарии:

1. Как раз то, что мне было нужно, спасибо!

Ответ №2:

 with conditions as (
select a[1]::int as product_id, a[2]::int as min_price
from (select regexp_split_to_array(unnest(string_to_array('1,50;2,100;3,20', ';')),',')) as dt(a)
)
select t.* from my_table t
  inner join conditions c on t.product = c.product_id
    and t.price >= c.min_price
 

данные испытаний:

 drop table if exists my_table;
create temp table if not exists my_table(product int, price int, note text);
insert into my_table
select 1,10, 'some info 1:10' union all
select 1,20, 'some info 1:20' union all
select 1,50, 'some info 1:50' union all
select 2,20, 'some info 2:10' union all
select 2,100, 'some info 2:100:1' union all
select 2,100, 'some info 2:100:2' union all
select 3,30, 'some info 3:30' union all
select 4,40, 'some info 4:40';
 

Результат:

 1   50  "some info 1:50"
2   100 "some info 2:100:1"
2   100 "some info 2:100:2"
3   30  "some info 3:30"


unnest(string_to_array('1,50;2,100;3,20', ';'))-- split CSV to rows
regexp_split_to_array(....,  ',') -- split CSV to columns
 

Комментарии:

1. Большое спасибо, очень интересное решение!