Aph*_*ppe 5 sql t-sql sql-server sql-server-2005
我有一张费用记录表(f_fee_item)如下:
Fee_Item_ID int
Fee_Basis_ID int
Start_Date date
End_Date date
Run Code Online (Sandbox Code Playgroud)
(删除了无关的列)
假设相同Fee_Basis_ID的记录不会重叠.
我需要Fee_Basis_ID在提供的@Query_Start_Date和之间的每个费用记录中找到每个缺口的Start_Date和End_Date @Query_End_Date.我需要这些数据来计算未收取费用的所有期间的应计费用.
如果给定的Fee_Basis_ID根本没有费用记录,我还需要查询返回记录(如果有帮助,Fee_Basis_ID是D_Fee_Basis.Fee_Basis_ID的外键).
例如:
@Query_Start_Date = '2011-01-01'
@Query_Start_Date = '2011-09-30'
Run Code Online (Sandbox Code Playgroud)
D_Fee_Basis:
F_Fee_Item
1
2
3
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
要求的结果:
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
Run Code Online (Sandbox Code Playgroud)
我已经尝试了不同的自我加入,试图让它工作但没有运气.
请帮忙!!
这是一个解决方案:
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)
Run Code Online (Sandbox Code Playgroud)
结果链接: https://data.stackexchange.com/stackoverflow/q/114193/