我认为一旦CASE找到匹配,它就会破坏并返回第一场比赛。但是,我从case语句中获得所有匹配。 e.g。
select distinct PERSON,
LOCATION,
(case
when LOCATION = 'CA' and PHONE is not null
then PHONE
when LOCATION = 'NY' and PHONE is not null
then PHONE
when LOCATION = 'FL' and PHONE is not null
then PHONE
when LOCATION = 'MA' and PHONE is not null
then PHONE
else '---'
end)
from DIRECTORY
where LOCATION in
( 'CA', 'NY', 'FL', 'MA' );
由于PERSON可以在每个州都有电话号码,我想要的是找到的第一个电话号码,基本上按州的顺序“排名”。我得到的是找到的所有电话号码。
... THX
答案 0 :(得分:2)
您可以为子查询中的每个州分配排名,然后为每个人保留最高排名记录:
WITH cte1 AS (
SELECT
PERSON,
LOCATION,
PHONE,
CASE WHEN LOCATION = 'CA' AND PHONE IS NOT NULL THEN 1
WHEN LOCATION = 'NY' AND PHONE IS NOT NULL THEN 2
WHEN LOCATION = 'FL' AND PHONE IS NOT NULL THEN 3
WHEN LOCATION = 'MA' AND PHONE IS NOT NULL THEN 4
ELSE 5 -- the NULL case
END AS LOCATION_RANK
FROM DIRECTORY
WHERE LOCATION IN ('CA', 'NY', 'FL', 'MA')
),
cte2 AS (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY t.PERSON ORDER BY t.LOCATION_RANK) rn
FROM cte1 t
)
SELECT
t.PERSON,
t.LOCATION,
COALESCE(t.PHONE, '---')
FROM cte2 t
WHERE t.rn = 1
答案 1 :(得分:0)
@ TimBielgeleisen的CTE方法可能更容易遵循和维护,但你可以使用keep dense_rank
在没有任何CTE的情况下做同样的事情,尽管你必须重复案例表达:
select person,
min(location) keep (dense_rank first order by
case when phone is null then 2 else 1 end,
case location when 'CA' then 1 when 'NY' then 2 when 'FL' then 3
when 'MA' then 4 end) as location,
coalesce(min(phone) keep (dense_rank first order by
case when phone is null then 2 else 1 end,
case location when 'CA' then 1 when 'NY' then 2 when 'FL' then 3
when 'MA' then 4 end), '---') as phone
from directory
where location in ('CA', 'NY', 'FL', 'MA')
group by person;
或者您可以将案例表达式移动到单个CTE或内联视图中,以使它们更易于维护:
select person,
min(location) keep (dense_rank first order by phone_rank, location_rank) as location,
coalesce(min(phone) keep (dense_rank first order by phone_rank, location_rank),
'---') as phone
from (
select person, location, phone,
case location when 'CA' then 1 when 'NY' then 2 when 'FL' then 3
when 'MA' then 4 end as location_rank,
case when phone is null then 2 else 1 end as phone_rank
from directory
where location in ('CA', 'NY', 'FL', 'MA')
)
group by person;
您仍然使用这些方法进行过一次排名,排名的处理方式略有不同,因此我不会期望性能差异(但总是最好检查您的实际数据,当然)。
答案 2 :(得分:0)
select distinct PERSON,
LOCATION,
(case
when LOCATION = 'CA' and PHONE is not null
then PHONE
else case
when LOCATION = 'NY' and PHONE is not null
then PHONE
else case
when LOCATION = 'FL' and PHONE is not null
then PHONE
else case
when LOCATION = 'MA' and PHONE is not null
then PHONE
else '---'
end end end end)
from DIRECTORY
where LOCATION in
( 'CA', 'NY', 'FL', 'MA' );