sql选择首选邮寄地址(如有指示)
我有一个客户表,有些客户可以有两个不同的地址。一个地址标记为主要地址,另一个地址标记为仅邮寄地址。如果客户有两个不同的地址,我只想提取标记为仅邮寄的地址。如果他们有多个帐户,但没有一个帐户只表示邮件,那么我只需要主帐户sql选择首选邮寄地址(如有指示),sql,Sql,我有一个客户表,有些客户可以有两个不同的地址。一个地址标记为主要地址,另一个地址标记为仅邮寄地址。如果客户有两个不同的地址,我只想提取标记为仅邮寄的地址。如果他们有多个帐户,但没有一个帐户只表示邮件,那么我只需要主帐户 Name | PrefMailings | Address John B. | Primary | PO Box 123 John B. | Mailing Only | 123 Street Tim T. | Pr
Name | PrefMailings | Address
John B. | Primary | PO Box 123
John B. | Mailing Only | 123 Street
Tim T. | Primary | 999 MyAddress
Tim T. | Joint | 999 MyAddress
Susan | Primary | 987 Home St.
结果
Name | PrefMailings | Address
John B. | Mailing Only | 123 Street
Tim T. | Primary | 999 MyAddress
Susan | Primary | 987 Home St.
在WHERE子句中,我使用了“PrefMailings=Primary或mailling Only”,但仍然没有得到首选的“mailling Only”地址。对于这位新手,任何建议都将不胜感激 您可以在标准SQL中使用
union all
和一些逻辑执行此操作:
select c.*
from customers c
where c.PrefMailings = 'Mailing Only'
union all
select c.*
from customers c
where c.PrefMailings = 'Primary' and
not exists (select 1
from customers c2
where c2.Name = c.Name and c2.PrefMailing = 'Mailing Only'
) ;
另一种方法是加入使用条件聚合的内联视图:
select c.*
from customers c
join (select sum(case prefmailings
when 'Mailing Only' then 1
end) as prim,
name
from customers
group by name) v
on (v.prim = 1
and c.prefmailings = 'Mailing Only')
or (v.prim is null
and c.prefmailings = 'Primary')
and c.name = v.name
小提琴:我意识到你将要看到的东西可能看起来很奇怪,但尽管它看起来很笨拙,但它的优点是只需要一次通过桌子,因此它可能比需要多次通过的替代品表现得更好
Name | PrefMailings | Address
John B. | Mailing Only | 123 Street
Tim T. | Primary | 999 MyAddress
Susan | Primary | 987 Home St.
还请注意,我已经扩展了格式,以便更容易理解所采用的方法。此语法适用于MySQL,但所有SQL风格中都存在等效的连接和子字符串函数
SELECT
name
, substr(
MIN(
concat(
CASE
WHEN prefmailings = 'Mailing Only' THEN 1
WHEN prefmailings = 'Primary' THEN 2
WHEN prefmailings = 'Joint' THEN 3
ELSE 9 END
, prefmailings
)
)
FROM 2
) AS prefmailings
, substr(
MIN(
concat(
CASE
WHEN prefmailings = 'Mailing Only' THEN 1
WHEN prefmailings = 'Primary' THEN 2
WHEN prefmailings = 'Joint' THEN 3
ELSE 9 END
, address
)
)
FROM 2
) AS prioritized_address
FROM customers
WHERE prefmailings IN ( 'Mailing Only' , 'Primary' )
GROUP BY
name
;
顺便说一下,WHERE子句是可选的,请注意,要更改优先级,只需更改分配给每种邮件类型的编号。该优先级编号可以保存在表或派生表中,以代替上面所示的硬编码。我希望您实际加入的依据不仅仅是名称,但您更了解您的数据,并且可能已经知道。。。也就是说,您可以通过名称进行多个连接,并确保您也获得了所有客户
select
c.name,
case when mo.name is not null then mo.addess
when p.name is not null then p.address
when j.name is not null then j.address
end FinalAddress
from
( select distinct name
from customers ) c
left join customers mo
on c.name = mo.name and mo.prefMailings = 'Mailing Only'
left join customers p
on c.name = p.name and p.prefMailings = 'Primary'
left join customers j
on c.name = j.name and j.prefMailings = 'Joint'
确保您的客户表在(名称、预邮件)上有索引,以优化联接。因此,您从每个客户开始,针对每个可能的邮寄地址类型再次加入客户表3次。如果“仅邮寄”存在,请抓住它。。。如果没有,请尝试“主要”获取它。。。如果失败,则“Joint”。请在问题中包含您正在尝试的SQL。您对中WHERE子句的最后一次评论不清楚,不足以理解正在发生的事情。请指定正在使用的数据库(对于所有与sql相关的问题都应这样做)