【问题标题】:Pick street with lowest seqnum if customer has one address available otherwise move to the next one如果客户有一个可用地址,则选择具有最低 seqnum 的街道,否则移动到下一个地址
【发布时间】:2021-12-19 05:29:28
【问题描述】:
cus_id seqnum street city
123 4 2 Main NYC
512 2 5 Elm LA
512 1 5 Elm LA
423 3 7 Wes Paris
512 3 4 Nav LA

我有一个带有 SeqNum 的表地址,我想选择最低 seqnum 的地址作为 MainAdress。如果客户有多个地址,则选择下一个为 ScondaryAddress。如果街道与前一条街道匹配,则跳过它并移动下一个 seqnum。

如果客户有多个地址,我的查询是选择错误的街道。

;with base AS 
(
    select SEQNUM,
         STREET AS MainAdress,
         --ROW_NUMBER() OVER(partition by street ORDER BY SEQNUM ASC) AS ROW,
   *
    FROM ADDRESS WHERE seqnum =1
   )
,ADDRESS AS
(
    SELECT 
           STREET AS SecondaryAdress,
* 
FROM BASE WHERE seqnum =2
)

但这不是动态获取街道

【问题讨论】:

  • 如果街道匹配 为什么这种情况甚至允许存在于您的表中?修复您的架构以防止重复,您的原始查询可以完美且更高效地运行。

标签: sql sql-server tsql common-table-expression


【解决方案1】:

我认为这是您要求的查询:

with base as
(
  select 
    ROW_NUMBER() over (partition by cus_id order by min(seqnum)) as rn,
    cus_id, min(seqnum) as seqnum, street, city
  from Address
  group by cus_id, street, city
)
select cus_id, max(MainAddress) MainAddress, max(SecondaryAddress) SecondaryAddress, city from (
  select 
    cus_id,
    case when rn = 1 then street  end MainAddress,
    case when rn = 2 then street  end SecondaryAddress,
    city
  from base
) as a
group by cus_id, city
having max(MainAddress) is not null or max(SecondaryAddress) is not null
order by cus_id

它返回这个:

cus_id MainAddress SecondaryAddress city
123 2 Main NYC
423 7 Wes Paris
512 5 Elm 4 Nav LA

DBFiddle:https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=b1b7caf84a374f2f387012e08fe49b59

【讨论】:

  • row_number() + min(seqnum) + group by cus_id, street, city → 太酷了!
  • 卡洛斯,尝试在地址表中再添加一个地址,例如 (512, 4, '6 Lane', 'WA')
  • @VadimLoboda 你是对的!!解决了 max(MainAddress) 不为 null 或 max(SecondaryAddress) 不为 null 的问题。很好的帮助!
【解决方案2】:
declare @table table (cus_id int, seqnum int, street varchar(10), city varchar (10));

insert into @table 
values
    (123, 4, '2 Main',  'NYC'   ),
    (512, 2, '5 Elm' ,  'LA'    ),
    (512, 1, '5 Elm' ,  'LA'    ),
    (423, 3, '7 Wes' ,  'Paris' ),
    (512, 3, '4 Nav' ,  'LA'    ),
    (512, 4, '6 Lane',  'WA'    );

with base as 
(
    select
        cus_id,
        seqnum,
        main_address        = concat(street, ' ', city),
        cnt                 = count(seqnum) over(partition by cus_id),
        secondary_address   = lead(concat(street, ' ', city), 1) over(partition by cus_id order by seqnum) 
    from
        @table
)
select top 1 with ties
    cus_id,
    main_address,
    secondary_address   
from
    base
where
    cnt = 1 or main_address != secondary_address
order by
    row_number() over(partition by cus_id order by seqnum);

SQL Fiddle

【讨论】:

    猜你喜欢
    • 2014-11-24
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    • 2013-08-10
    相关资源
    最近更新 更多