SQL首选一对多关系

SQL首选一对多关系,sql,tsql,sql-server-2008,Sql,Tsql,Sql Server 2008,假设我在客户和地址之间有一对多的关系 客户可以有不同地址类型的多个地址(例如家庭、邮政、工作、公司、未来),并且可能没有地址或相同类型的多个地址(在这种情况下,我很乐意选择第一个地址) 我的数据由clientid、address和addresstypeid组成。addresstypeid的首选顺序是2,3,4,1:因此,如果客户机的addresstypeid为2,则返回记录,如果不是,则返回3,如果不是4,如果不是1,如果不是null 有没有比这更优雅的方法 declare @addresses

假设我在客户和地址之间有一对多的关系

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

我的数据由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

这两个表很好,但是当你使它们永久不变时,应该考虑索引:

关于你的最后一个问题,我会稍微修改一下

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