【问题标题】:Find gaps in time not covered by records with start date and end date查找具有开始日期和结束日期的记录未涵盖的时间间隔
【发布时间】:2011-10-03 10:04:25
【问题描述】:

我有一张费用记录表 (f_fee_item),如下所示:

Fee_Item_ID    int
Fee_Basis_ID   int
Start_Date     date
End_Date       date

(删除不相关的列)

假设相同 Fee_Basis_ID 的记录不会重叠。

我需要在提供的@Query_Start_Date@Query_End_Date 之间找到每个Fee_Basis_ID 的费用记录中每个空白的开始日期和结束日期。我需要这些数据来计算未收取费用的所有期间的应计费用。

如果给定的 Fee_Basis_ID 根本没有费用记录,我还需要查询返回记录(如果有帮助,Fee_Basis_ID 是 D_Fee_Basis.Fee_Basis_ID 的外键)。

例如:

@Query_Start_Date = '2011-01-01'
@Query_Start_Date = '2011-09-30'

D_Fee_Basis:

F_Fee_Item
1
2
3

F_Fee_Item:

Fee_Item_ID  Fee_Basis_ID  Start_Date  End_Date
1            1             2011-01-01  2011-03-31
2            1             2011-04-01  2011-06-30
3            2             2011-01-01  2011-03-31
4            2             2011-05-01  2011-06-30

要求的结果:

Fee_Basis_ID   Start_Date  End_Date
1              2011-07-01  2011-09-30
2              2011-04-01  2011-04-30
2              2011-07-01  2011-09-30
3              2011-01-01  2011-09-30

几天来,我一直在尝试不同的自联接以使其正常工作,但没有成功。

请帮忙!!

【问题讨论】:

  • F_Fee_Item 表有多少条记录?
  • 预计在系统生命周期内保持在 5 位数以下

标签: sql sql-server sql-server-2005 tsql


【解决方案1】:

这是一个解决方案:

declare @Query_Start_Date date= '2011-01-01' 
declare @Query_End_Date date = '2011-09-30' 

declare @D_Fee_Basis table(F_Fee_Item int)
insert @D_Fee_Basis values(1) 
insert @D_Fee_Basis values(2) 
insert @D_Fee_Basis values(3) 

declare @F_Fee_Item table(Fee_Item_ID int, Fee_Basis_ID int,Start_Date date,End_Date date)
insert @F_Fee_Item values(1,1,'2011-01-01','2011-03-31') 
insert @F_Fee_Item values(2,1,'2011-04-01','2011-06-30') 
insert @F_Fee_Item values(3,2,'2011-01-01','2011-03-31')
insert @F_Fee_Item values(4,2,'2011-05-01','2011-06-30')

;with a as
(-- find all days between Start_Date and End_Date
select @Query_Start_Date d
union all 
select dateadd(day, 1, d)
from a
where d <  @Query_end_Date
), b as
(--find all unused days
select a.d, F_Fee_Item Fee
from a, @D_Fee_Basis Fee
where not exists(select 1 from @F_Fee_Item where a.d between Start_Date and End_Date and Fee.F_Fee_Item = Fee_Basis_ID)
),
c as
(--find all start dates
select d, Fee, rn = row_number() over (order by fee, d) from b 
where not exists (select 1 from b b2 where dateadd(day,1, b2.d) = b.d and b2.Fee= b.Fee)
),
e as
(--find all end dates
select d, Fee, rn = row_number() over (order by fee, d) from b 
where not exists (select 1 from b b2 where dateadd(day,-1, b2.d) = b.d and b2.Fee= b.Fee)
)
--join start dates with end dates
select c.Fee Fee_Basis_ID, c.d Start_Date, e.d End_Date from c join e on c.Fee = e.Fee and c.rn = e.rn
option (maxrecursion 0)

结果链接: https://data.stackexchange.com/stackoverflow/q/114193/

【讨论】:

  • 完美。谢谢您的帮助。我真的需要正确学习 CTE。
猜你喜欢
  • 1970-01-01
  • 2021-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多