2011-08-25 68 views
0

假设我在客户端和地址之间有一对多的关系。SQL首选的一对多关系

客户端可以有不同地址类型(例如,家庭,邮政,工作,公司,未来)的多个地址,并且可能没有相同类型的地址或多个地址(在这种情况下,我很乐意采取第一次出现)。

我的数据由clientid,address和addresstypeid组成。 addresstypeid的首选顺序是2,3,4,1:因此,如果客户端的addresstypeid为2,则返回该记录,如果不是3则返回记录,如果不是4,则返回1,否则返回null。

是否有比这样的更优雅的方式来做到这一点?

declare @addresses table 
(
    clientid int, 
    address varchar(10), 
    addresstypeid int 
) 
--2,3,4,1 
insert into @addresses (clientid, address, addresstypeid) 
select 1, '1a', 1 union all 
select 1, '1b', 2 union all 
select 1, '1c', 3 union all 
select 1, '1d', 4 union all 
select 2, '2a', 2 union all 
select 2, '2b', 3 union all 
select 2, '2c', 4 union all 
select 2, '2a', 1 union all 
select 3, '3a', 3 union all 
select 3, '3b', 4 union all 
select 3, '3c', 1 union all 
select 4, '4a', 3 union all 
select 4, '4b', 4 union all 
select 5, '5a', 4 union all 
select 6, '6a', 4 union all 
select 6, '6b', 1 union all 
select 7, '7a', 1 union all 
select 7, '7b', 4 

declare @ranktable table 
(
    addresstypeid int, 
    rank int 
) 

insert into @ranktable(addresstypeid, rank) 
select 2, 1 union all 
select 3, 2 union all 
select 4, 3 union all 
select 1, 4 

select 
    e.address, 
    e.clientid, 
    e.addresstypeid 
from 
    @addresses e 
    inner join @ranktable r on 
     e.addresstypeid = r.addresstypeid 
    inner join (select 
        em.clientid, 
        min(rank) minrank 
       from @addresses em 
        inner join @ranktable ranks on 
         em.addresstypeid = ranks.addresstypeid 
       group by 
        clientid) clientranks on 
     e.clientid = clientranks.clientid and 
     r.rank = clientranks.minrank 

回答

2

两个表都很好,不过你应该考虑索引时,你让他们永久:)

在最终的查询方面,我会改变它咯...

WITH 
    sorted_data 
AS 
(
    SELECT 
    [a].*, 
    ROW_NUMBER() OVER (PARTITION BY [a].clientid ORDER BY [r].rank) AS sequence_id 
    FROM 
    @addresses  AS [a] 
    INNER JOIN 
    @ranktable  AS [r] 
     ON a.addresstypeid = r.addresstypeid 
) 

SELECT 
    * 
FROM 
    sorted_data 
WHERE 
    sequence_id = 1