#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 не очень хорошо для производительности, но в любом случае, я должен запускать это один раз в день.