我想根据以下规则为每个用户选择一个电子邮件地址。 如果preferred_email为Y,请选择该电子邮件地址(email2@gmail.com)。 如果preferred_email不是Y,请使用该电子邮件地址。 某些用户可能只有preferred_email值为N. 我尝试过使用case语句,但它没有返回正确的结果。
这是该表的一个例子。
user_id email_address preferred_email
25 email1@gmail.com N
25 email2@gmail.com Y
26 email3@gmail.com N
27 email4@gmail.com N
答案 0 :(得分:2)
SELECT user_id,
MAX( email_address ) KEEP ( DENSE_RANK FIRST ORDER BY preferred_email DESC, ROWNUM )
AS email_address
FROM your_table
GROUP BY user_id
或
SELECT user_id,
email_address
FROM (
SELECT t.*,
ROW_NUMBER() OVER ( PARTITION BY user_id
ORDER BY preferred_email DESC, ROWNUM )
AS rn
FROM your_table t
)
WHERE rn = 1;
答案 1 :(得分:0)
在Oracle 12.1及更高版本中,可以使用match_recognize
子句轻松完成此操作,如下所示:
select user_id, email_address
from inputs
match_recognize (
partition by user_id
order by preferred_email desc nulls last
all rows per match
pattern ( ^x )
define x as 0 = 0
)
;
但是,此解决方案(以及此处提出的其他一些解决方案)存在潜在的弱点:它依赖于'Y'
vs 'N'
的显式排序,并假设这些是唯一的值可能在preferred_email
列中(以及该列不可为空)。
如果列preferred_email
不被限制为不可为空且只有可能的值'Y'
和'N'
,那么最好有一个像
order by case preferred_email when 'Y' then 0 end [...]
不幸的是,match_recognize
子句只能按列排序,而不能按表达式排序。 (希望将来能够解决这个问题!)在这种情况下,使用FIRST / LAST聚合函数的聚合解决方案(如MT0的答案)是最佳选择 - 但ORDER BY子句也相应更改。
select user_id,
max(email_address) keep (dense_rank first
order by case preferred_email when 'Y' then 0 end) as email_address
from inputs
group by user_id
;