我有一张桌子,包括帐户及其余额。我想报告每一天的余额,而缺少的日子要报告最后一天。 表帐户:
AccountName Date Balance
thomas 2008-10-09 1000
thomas 2008-10-20 5000
david 2008-02-18 2000
david 2008-03-10 200000
假设我们想要2018-10年度的报告,我需要获得类似的信息
thomas 2008-10-01 0
...
thomas 2008-10-09 1000
thomas 2008-10-10 1000
...
thomas 2008-10-20 5000
...
thomas 2008-10-31 5000
我走了这么远:
DECLARE @StartDate datetime = '2008/10/9';
DECLARE @EndDate datetime = '2008/10/20';
WITH theDates AS
(
SELECT @StartDate as theDate
UNION ALL
SELECT DATEADD(day, 1, theDate)
FROM theDates
WHERE DATEADD(day, 1, theDate) <= @EndDate
)
select * from accounts a
right outer join thedates d on a.date=d.theDate
order by thedate
结果:
AccountNo Date Balance theDate
----------- ---------- -------- ----------
thomas 2008-10-09 1000 2008-10-09
NULL NULL NULL 2008-10-10
NULL NULL NULL 2008-10-11
NULL NULL NULL 2008-10-12
NULL NULL NULL 2008-10-13
NULL NULL NULL 2008-10-14
NULL NULL NULL 2008-10-15
NULL NULL NULL 2008-10-16
NULL NULL NULL 2008-10-17
NULL NULL NULL 2008-10-18
NULL NULL NULL 2008-10-19
thomas 2008-10-20 5000 2008-10-20
有什么主意吗?
更新: 我最终使用光标。此版本可以完美运行,包括帐户没有条目的情况。
DECLARE @Date datetime
declare @result table (accountname nvarchar(50), balance int, date datetime)
DECLARE @StartDate datetime = '2008/10/1';
DECLARE @EndDate datetime = '2008/10/29';
declare cur cursor for
WITH theDates AS
(
SELECT @StartDate as theDate
UNION ALL
SELECT DATEADD(day, 1, theDate)
FROM theDates
WHERE DATEADD(day, 1, theDate) <= @EndDate
)
select * from theDates
open cur
fetch next from cur into @date
while @@FETCH_STATUS=0
begin
insert into @result
select b.accountName, isnull(balance,
(select isnull((select top 1 balance from accounts where date<@date and accountName=b.accountName order by date desc),0))
), @date from
(select * from accounts where date = @date) a
right outer join (select distinct(accountname) from accounts ) b on a.accountname = b.accountname
fetch next from cur into @date
end
close cur
deallocate cur
select * from @result
答案 0 :(得分:2)
尝试一下:
DECLARE @StartDate datetime = '2008/10/9';
DECLARE @EndDate datetime = '2008/10/20';
WITH theDates AS
(
SELECT @StartDate as theDate
UNION ALL
SELECT DATEADD(day, 1, theDate)
FROM theDates
WHERE DATEADD(day, 1, theDate) <= @EndDate
),
acc AS(
SELECT a.AccountName,
a.Balance,
a.Date,
isnull(c.CloseDate, cast(GETDATE()as date)) as CloseDate
FROM accounts a
CROSS APPLY(SELECT MIN(b.Date) as CloseDate
FROM accounts b
WHERE b.Date > a.Date) c
)
SELECT a.AccountName, a.Balance, a.Date, d.theDate
FROM acc a, theDates d
WHERE a.Date <= d.theDate
AND a.CloseDate > d.theDate
option (maxrecursion 0)
结果:
AccountName Balance Date theDate
----------- ----------- ------------------- -----------------------
thomas 1000 2008-10-09 00:00:00 2008-10-09 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-10 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-11 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-12 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-13 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-14 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-15 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-16 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-17 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-18 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-19 00:00:00.000
thomas 5000 2008-10-20 00:00:00 2008-10-20 00:00:00.000
答案 1 :(得分:1)
您可以尝试使用聚合函数MIN
和MAX
创建日历表,然后使用OUTER JOIN
WITH theDates AS
(
SELECT AccountName, MIN(Date) as StartDt,MAX(Date) EndDt
FROM accounts
GROUP BY AccountName
UNION ALL
SELECT AccountName,DATEADD(day, 1, StartDt),EndDt
FROM theDates
WHERE DATEADD(day, 1, StartDt) <= EndDt
)
select d.AccountName,
d.StartDt [date],
ISNULL(a.Balance,0) Balance
from accounts a
LEFT join thedates d on a.date=d.StartDt
order by StartDt