2011-08-25 65 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