如果指示,sql选择首选邮寄地址

时间:2014-08-30 00:26:33

标签: sql

我有一个客户表,有些客户可以有两个不同的地址。一个地址标记为主要,另一个地址标记为仅邮寄。如果客户有两个不同的地址,我想只提取标记为仅邮寄的地址。如果他们有多个帐户但没有一个表示仅邮件,那么我只想要主要帐户。

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或​​Mailing Only"仍然没有得到首选的"仅邮寄"地址。任何建议都非常感谢这个新人。

4 个答案:

答案 0 :(得分:0)

您可以使用union all和某些逻辑在标准SQL中执行此操作:

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'
                 ) ;

答案 1 :(得分:0)

另一种方法是加入使用条件聚合的内联视图:

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

小提琴: http://sqlfiddle.com/#!2/cdc15/8/0

答案 2 :(得分:0)

我意识到你将要看到的东西可能看起来很奇怪,但是虽然它看起来很笨拙但它的优点是只需要一次通过桌子,因此它可能比需要多次通过的替代品表现更好。

请注意我已经扩展了格式,以便更容易理解所采用的方法。此语法适用于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
;

See this SQLfiddle demo

顺便说一句WHERE子句是可选的,并注意要更改优先级,只需更改分配给每种邮件类型的编号。该优先级数字可以保存在表格或派生表中,以代替上面的硬编码。

答案 3 :(得分:0)

我希望你实际上加入的不仅仅是基于名称的东西,但你知道你的数据更好,而且可能已经知道......那就是说,你可以通过名字进行多次加入并确保你做也得到所有客户。

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'

确保您的customer表上有(name,prefMailings)索引以优化连接。因此,您从每个客户开始,并针对每种可能的邮寄地址类型再次加入客户表3次。如果存在“仅邮寄”,请抓住它...如果没有,请尝试“初级”获取它...如果失败,则“联合”。