【问题标题】:Consolidate information (time serie) from two tables合并来自两个表的信息(时间序列)
【发布时间】:2021-06-01 08:30:05
【问题描述】:

MS SQL 服务器

我有两个表,来自同一客户的不同帐户:

表1:

ID ACCOUNT FROM TO
1 A 01.10.2019 01.12.2019
1 A 01.02.2020 09.09.9999

和表2:

ID ACCOUNT FROM TO
1 B 01.12.2019 01.01.2020

因此,我想要一张表格来总结这位客户的故事,并显示他何时拥有活跃帐户以及何时没有。

结果:

ID FROM TO ACTIV Y/N
1 01.10.2019 01.01.2020 Y
1 02.01.2020 31.01.2020 N
1 01.02.2020 09.09.9999 Y

有人可以帮我一些想法如何进行吗?

【问题讨论】:

  • 你想要UNION
  • 如果我使用 UNION,我会得到 3 行。我需要客户不活跃时的信息,如果帐户之间存在重叠,我需要时间序列的合并。
  • 我正在使用 MS SQL Server
  • 这是典型的间隙和孤岛问题。如果你在网上搜索,这个问题有很多解决方案
  • @VenkataramanR,我想说它很容易转换为带有日历表的岛屿。

标签: sql sql-server merge


【解决方案1】:

这是典型的间隙和孤岛问题,通常不容易解决。

你可以使用这个查询来实现你的目标,我会稍微解释一下。

你可以测试on this db<>fiddle

首先...我已将您的两个表合二为一以简化查询。

-- ##table1
select 1 as ID, 'A' as ACCOUNT, convert(date,'2019-10-01') as F, convert(date,'2019-12-01') as T into ##table1
union all
select 1 as ID, 'A' as ACCOUNT, convert(date,'2020-02-01') as F, convert(date,'9999-09-09') as T

-- ##table2
select 1 as ID, 'B' as ACCOUNT, convert(date,'2019-12-01') as F, convert(date,'2020-01-01') as T into ##table2

-- ##table3
select * into ##table3 from ##table1 union all select * from ##table2

然后,您可以使用例如这样的查询来获取您的差距和孤岛。 它结合递归 cte 生成日历 (cte_cal) 和 laglead 操作来获取上一条/下一条记录信息以构建间隙。

with 
cte_cal as (
  select min(F) as D from ##table3 
  union all
  select dateadd(day,1,D) from cte_cal where d < = '2021-01-01'
),
table4 as (
  select t1.ID, t1.ACCOUNT, t1.F, isnull(t2.T, t1.T) as T, lag(t2.F, 1,null) over (order by  t1.F) as SUP
  from ##table3 t1
    left join ##table3 t2
      on t1.T=t2.F
)
select 
  ID,
  case when T = D then F else D end as "FROM",
  isnull(dateadd(day,-1,lead(D,1,null) over (order by D)),'9999-09-09') as "TO",
  case when case when T = D then F else D end = F then 'Y' else 'N' end as "ACTIV Y/N"
from (
  select *
  from cte_cal c 
    cross apply (
      select t.*
      from table4 t
      where t.SUP is null 
        and (
          c.D = t or 
          c.D = dateadd(day,1,t.T)    
        )
      ) t
  union all
  select F, * from table4 where T = '9999-09-09'
  ) p
order by 1
option (maxrecursion 0)

'9999-09-09' 这样的日期必须被视为例外,否则我必须在该日期之前创建一个日历,因此查询需要很长时间才能解决。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-09
    • 2016-06-19
    • 2018-07-03
    • 2014-04-11
    • 1970-01-01
    • 2015-06-06
    相关资源
    最近更新 更多