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相关的问题都应这样做)