2012-06-20 55 views
4

我试图运行以下查询,但不确定如何将其限制为仅一个结果。 在下面的查询中,clientcontactid 21901适用的客户端有2个地址,即2个结果返回。MS SQL 2008加入 - 从许多结果中选择一个

查询:

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 

我需要返回的结果之一客户联系,则优先级为上一个与城市的它。我试过选择顶部(1),但我认为这是由于联合迫使多个记录回来。如何返回只有1结果的任何帮助,以及如何控制,将不胜感激!

感谢

回答

6

尝试:

;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 
0

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

+0

问题放在哪里城市不是null是否有一些记录将在城市中为null,如果没有其他选择,我很乐意返回这些记录。 你会把选择的顶部1放在哪里?如果它进入顶端,那么它将只返回带有clientcontact 21901的顶部行,并且不会返回clientcontact 17275的顶部行! – franglais

4

我通常会优先处理结果的做法是实际分配优先级值列。在这种情况下,它可以保持简单,因为只有一个重点:随着城市的记录来到城市之前没有:

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 
1

大,但它的工作原理:

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 <> '') 
) 
+0

你是对的 - 它很大,但确实有效!只是出于兴趣,** ad.city不是null或ad.city <> ** **和** isnull(ad.city,'')<>'** **之间有任何区别吗? – franglais

+1

@ sam.clements nop,你可以使用'isnull'代替:) –

0

试试这个:

;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