按优先级加入一对多获取一行

时间:2012-06-21 22:22:51

标签: sql sql-server-2008 tsql

我有一个联系人表:

ID  NAME
--- ----
1   KK
2   JKI
3   HU

我有一个电话桌:

ID  ContactID  Phone  Type
--- ---------  -----  --------
1   1          569    Business
2   1          896    Mobile
3   1          258    Fax
4   2          369    Mobile
5   3          124    Fax
6   2          496    Fax

我希望所有联系人都至少有一个电话号码。要显示的电话号码应为Business,如果没有可用的Busniess Type,则为Mobile,如果没有可用的Mobile类型,则传真else null

示例结果:

ID  NAME   PHONE
--- ------ ------
1   KK     569   -- Business present
2   JKI    369   -- Business not present but mobile present
3   HU     124   -- only fax present

4 个答案:

答案 0 :(得分:4)

;WITH [prior](i,t) AS 
(
    SELECT 1, 'Business'
    UNION ALL SELECT 2, 'Mobile'
    UNION ALL SELECT 3, 'Fax'
),
x AS 
(
  SELECT c.ID, c.Name, p.Phone,
    rn = ROW_NUMBER() OVER (PARTITION BY c.ID ORDER BY r.i)
  FROM dbo.Contacts AS c
  LEFT OUTER JOIN dbo.Phone AS p
  ON p.ContactID = c.ID
  LEFT OUTER JOIN [prior] AS r
  ON r.t = p.[Type]
)
SELECT ID, Name, Phone FROM x
WHERE rn = 1;

如果您想取消没有手机的联系人,只需将LEFT OUTER的两个实例更改为INNER

答案 1 :(得分:2)

select  c.ID
,       c.Name
,       coalesce(business.Phone, mobile.Phone, fax.Phone) as Phone
from    Contacts c
left join
        Phone business
on      business.ContactID = c.ID
        and business.type = 'Business'
left join
        Phone mobile
on      mobile.ContactID = c.ID
        and mobile.type = 'Mobile'
left join
        Phone fax
on      fax.ContactID = c.ID
        and fax.type = 'Fax'
where   coalesce(business.Phone, mobile.Phone, fax.Phone) is not null

答案 2 :(得分:1)

您的数据模型不能很好地有效地查询,但这可能有用:

SELECT C.ID, C.Name, COALESCE(
    (SELECT TOP 1 P.Phone FROM Phones P WHERE P.ContactID = C.ID AND P.[Type] = 'Business'),
    (SELECT TOP 1 P.Phone FROM Phones P WHERE P.ContactID = C.ID AND P.[Type] = 'Mobile'),
    (SELECT TOP 1 P.Phone FROM Phones P WHERE P.ContactID = C.ID AND P.[Type] = 'Fax')
  ) Phone
  FROM Contacts C

答案 3 :(得分:1)

我能想到的最紧凑的解决方案是,

; WITH CTE AS (
    SELECT 
    c.ID, c.NAME, p.Phone
    , r = ROW_NUMBER()OVER(PARTITION BY c.ID ORDER BY CASE p.[TYPE] WHEN 'Business' THEN 1 WHEN 'Mobile' THEN 2 ELSE 3 END)
    FROM Contacts c
    LEFT JOIN Phone p ON p.ContactID = c.ID AND p.[TYPE] IN ('Business','Mobile','Fax')
    WHERE EXISTS(SELECT 1 FROM Phone WHERE ContactID = c.ID)
)
SELECT ID, NAME, Phone
FROM CTE
WHERE r = 1;

此解决方案返回

  • 按指定顺序与第一个匹配的手机联系
  • 如果手机号码存在但没有指定类型
  • ,请与NULL手机#联系
  • 根本没有电话的联系人
  • 没有结果