我想生成一份年度报告,用户在月份和年份开始插入帐号。使用这些数据我想生成一个临时表,它开始从选定年份的起始月份到12个月后提供用户资源使用情况统计数据。
我正在使用光标这样做。现在,当用户未使用该资源达到某个月时,就会出现问题。我仍然希望临时表为这些月生成空列。我该怎么办?
declare @account_no varchar(max)
declare @resourse_usage int
declare @month int
declare @year int
declare @month1 int
declare @year1 int
declare @tempdatatable table
( account_no varchar(max),
resourse_usage int,
month int,
year int,
)
DECLARE array1 cursor for
select account_no,resourse_usage,month,year from tblstats where account_no=1 and month>@month and year=@year
open array1
fetch next from array1 into @account_no,@resourse_usage,@month1,@year1
while @@fetch_status=0
begin
insert into @tempdatatable
(account_no,resourse_usage,month,year)
values
(@account_no,@resourse_usage,@month1,@year1)
fetch next from array1 into @account_no,@resourse_usage,@month1,@year1
end
close array1
deallocate array1
select * from @tempdatatable
答案 0 :(得分:2)
首先,没有理由为此使用游标;简单地使用select语句将允许优化器完成其工作,即使没有任何额外的优化,不使用游标也会运行得更快。 SQL是关于处理元组(行)的集合,如果你可以用集合来表示问题,那么有很多智能代码可以为你工作。
在这种情况下,解决方案是在两个集合的联合上使用group by
。第一组是您在问题中选择的那一组(我假设您在名为@account
的变量中有目标帐号#):
select account_no,resourse_usage,month,year
from tblstats
where account_no=@account and (
month >= @month and year = @year or
month < @month and year = @year+1
)
第二组是报告期内所有月份的集合:
;With Months( Month ) as
(
Select 1 as Month
union all
Select Month + 1
from Months
where month < 12
)
select @account as account_no, NULL as resourse_usage, month,
case when month >= @month then @year else @year+1 end as year
from Months
将所有这些结合起来,我们得到:
;With Months( Month ) as
(
Select 1 as Month
union all
Select Month + 1
from Months
where month < 12
)
select account_no, max(resourse_usage) as resourse_usage, month, year
from (
select account_no, resourse_usage, month, year
from tblstats
where account_no=@account and (
month >= @month and year = @year or
month < @month and year = @year+1
)
union
select @account as account_no, NULL as resourse_usage, month,
case when month >= @month then @year else @year+1 end as year
from Months
) G
group by account_no, month, year
答案 1 :(得分:1)
尝试使用months声明临时表并更改游标中的语句:
declare @tblMonths table(month int)
insert into @tblMonths (month) values (1), (2), (3), (4), (5), (6) ,(7), (8), (9), (10), (11), (12)
和 游标语句
select t.account_no,t.resourse_usage, isnull(t.month, m.month) as month, isnull(t.year, @year)
from tblstats t
right join @tblMonths m on t.month = m.month
where t.account_no=1 and t.month>@month and t.year=@year