【问题标题】:MS SQL 2008 join - select one from many resultsMS SQL 2008 连接 - 从多个结果中选择一个
【发布时间】:2012-06-22 09:44:02
【问题描述】:

我正在尝试运行以下查询,但不确定如何将其限制为仅一个结果。 在下面的查询中,clientcontactid 21901 工作的客户端有 2 个地址,这意味着返回 2 个结果。

查询:

select  cc.contactpersonid,
    cc.clientcontactid,
    ad.city,
    ad.addressid
from SavedList sl
inner join ClientContacts cc on cc.ContactPersonId = sl.ObjectId
inner join Clients c on c.ClientID = cc.ClientId
inner join Address ad on c.ClientID = ad.ObjectId
where sl.SavedListId = 2117

结果:

contactpersonid clientcontactid city    addressid
87934           21901                   145186
87934           21901           London  1130705
89778           17275           Leeds   145368

我需要为客户联系人 21901 返回其中一个结果,优先级是包含城市的结果。我试过 select top (1) 但我认为这归结为强制多条记录返回的连接。任何有关如何仅返回 1 个结果以及如何控制该结果的帮助将不胜感激!

谢谢

【问题讨论】:

    标签: sql sql-server-2008 join


    【解决方案1】:

    试试:

    ;WITH a AS (
    select  cc.contactpersonid,
        cc.clientcontactid,
        ad.city,
        ad.addressid,
        ROW_NUMBER() OVER (PARTITION BY cc.clientcontactid ORDER BY ad.city DESC) AS RowNum
        from SavedList sl
        inner join ClientContacts cc on cc.ContactPersonId = sl.ObjectId
        inner join Clients c on c.ClientID = cc.ClientId
        inner join Address ad on c.ClientID = ad.ObjectId
        where sl.SavedListId = 2117
    )
    
    SELECT  *
    FROM    a
    WHERE   RowNum = 1
    

    【讨论】:

      【解决方案2】:

      我通常对结果进行优先级排序的方法是实际分配一个优先级值列。在这种情况下,它可以保持简单,因为只有一个优先级:有城市的记录排在没有城市的前面:

      with q as(
      select  cc.contactpersonid,
          cc.clientcontactid,
          ad.city,
          ad.addressid,
          case when ad.city is null then 0 else 1 end prior
      from SavedList sl
      inner join ClientContacts cc on cc.ContactPersonId = sl.ObjectId
      inner join Clients c on c.ClientID = cc.ClientId
      inner join Address ad on c.ClientID = ad.ObjectId
      where sl.SavedListId = 2117
      )
      select top 1 * from q order by prior desc
      

      【讨论】:

        【解决方案3】:

        大但有效:

        select  cc.contactpersonid,
                cc.clientcontactid,
                ad.city,
                ad.addressid
        from SavedList sl
        inner join ClientContacts cc on cc.ContactPersonId = sl.ObjectId
        inner join Clients c on c.ClientID = cc.ClientId
        inner join Address ad on c.ClientID = ad.ObjectId
        where sl.SavedListId = 2117 and (ad.city is not null or ad.city <> '')
        UNION
        select  cc.contactpersonid,
                cc.clientcontactid,
                ad.city,
                ad.addressid
        from SavedList sl
        inner join ClientContacts cc on cc.ContactPersonId = sl.ObjectId
        inner join Clients c on c.ClientID = cc.ClientId
        inner join Address ad on c.ClientID = ad.ObjectId
        where sl.SavedListId = 2117 and (ad.city is null or ad.city = '')
        and cc.clientcontactid not in (
          select  cc.clientcontactid
          from SavedList sl
          inner join ClientContacts cc on cc.ContactPersonId = sl.ObjectId
          inner join Clients c on c.ClientID = cc.ClientId
          inner join Address ad on c.ClientID = ad.ObjectId
          where sl.SavedListId = 2117 and (ad.city is not null or ad.city <> '')
        )
        

        【讨论】:

        • 你是对的 - 它很大,但它确实有效!只是出于兴趣, ad.city is not null 或 ad.city ''isnull(ad.city,'')'' ?
        • @sam.clements nop,你可以改用isnull :)
        【解决方案4】:

        您可以通过添加条件 city is not NULL 来尝试 select top 1 record

        【讨论】:

        • 将 where city 不为 null 的问题是有些记录在 city 中为 null,如果没有其他选择,我很乐意返回这些记录。您将选择顶部 1 放在哪里?如果它进入顶部,那么它只会返回带有 clientcontact 21901 的第一行,并且不会返回 clientcontact 17275 的那一行!
        【解决方案5】:

        试试这个:

        ;WITH cte
             AS (SELECT cc.contactpersonid,
                        cc.clientcontactid,
                        ad.city,
                        ad.addressid,
                        Row_number() OVER (PARTITION BY cc.clientcontactid ORDER BY CASE WHEN ad.city <> '' THEN 1 ELSE 0 END) rn
                 FROM   SavedList sl
                        INNER JOIN ClientContacts cc
                          ON cc.ContactPersonId = sl.ObjectId
                        INNER JOIN Clients c
                          ON c.ClientID = cc.ClientId
                        INNER JOIN Address ad
                          ON c.ClientID = ad.ObjectId
                 WHERE  sl.SavedListId = 2117)
        SELECT contactpersonid,
               clientcontactid,
               city,
               addressid
        FROM   cte
        WHERE  rn = 1
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-11-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多