ОПЕРАТОР CASE В ПРЕДЛОЖЕНИИ WHERE в ЗАПРОСЕ

#sql #postgresql

#sql #postgresql

Вопрос:

Моя таблица выглядит следующим образом

 ID    |             email                 | ref
------- ----------------------------------- ------------
    12 | test@testmail.com                 |          0
    12 | test@testmail.com                 |          1
  

Теперь требование запроса состоит в том, чтобы получить идентификатор и адрес электронной почты, ссылка на который равна 0, однако
если электронное письмо имеет значение null с ссылкой 0, то оно должно принимать значение электронной почты ref 1.
Если оба ref имеют значение email, то по умолчанию оно должно принимать значение 0.

Я попытался с приведенным ниже запросом, но это не удается, он дает мне оба значения

 select 
    id, 
    email, 
    ref 
from 
    table1 
where ref in (case when email is not null then 0 else 1 end) and ID=12;
  

Есть ли какой-либо способ добиться этого?

Ответ №1:

Использовать distinct on :

 select distinct on (email) t1.*
from table1 t1
order by email, ref asc;
  

Это возвращает по одной строке на email . Возвращаемая строка — это строка с меньшим значением ref.

Примечание: distinct on является удобным расширением Postgres к стандарту SQL. Он недоступен в других базах данных.

Редактировать:

Я думаю, вам может понадобиться по одной строке на id . Если это так:

 select distinct on (id) t1.*
from table1 t1
order by id,
         (case when ref = 0 and email is not null then 1
               when ref = 1 then 2
               else 3
          end);
  

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

1. если предположить, что электронное письмо с ссылкой 1 равно нулю, то оно вернет оба значения, однако требуется вернуть единственное электронное письмо с ссылкой 0 и переключиться на электронное письмо с ссылкой 1, только если значение в электронном письме с ссылкой 0 равно нулю

Ответ №2:

использование приведенной ниже логики должно дать вам ожидаемый результат

 ; with cte as 
(
select id, email, rn=row_number() over (partition by id order by ref asc) 
from table1 
where (email is NOT NULL OR ref=1) 
)
select id, email from cte
where rn=1 
  

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

1. Спасибо, это работает в соответствии с требованием, однако, я думаю, что использование cte не очень хорошо для производительности, но в любом случае, я должен запускать это один раз в день.