在某些应用中, 我正在使用以下sql查询,
SELECT DATE,
SUM( CASE WHEN project_id = '6' THEN spent_time ELSE 0 END ) project_1,
SUM( CASE WHEN project_id = '41' THEN spent_time ELSE 0 END ) project_2,
SUM( CASE WHEN project_id = '14' THEN spent_time ELSE 0 END ) project_3
FROM tasks
WHERE user_id =80
GROUP BY DATE, project_id
它返回以下输出
但是在上面的SQL查询中我使用了预定义的列。我正在寻找一个解决方案,我有动态列说我手头没有项目ID。
另外,我想要一个额外的列,显示每行的project_1,project_2,project_3的总和。
因此,结果结构将为DATE,PROJECT_1,PROJECT_2,PROJECT_3,SUM_OF_PROJECTS
我还可以获取行不存在的数据吗?例如,以下示例中的2012-04-03
。优选地不使用日历表
任何指针都会受到赞赏。
其他细节:数据库 - mysql,Rails(2.3.14)
答案 0 :(得分:2)
我不确定您使用的是什么数据库引擎,但下面的示例使用的是Microsoft SQL Server。我相信它可以很容易地适应其他引擎。
首先,我使用以下查询创建了一些设置数据:
create table tasks(
[id] int not null identity(1,1),
[DATE] smalldatetime not null,
project_id int not null,
spent_time int not null,
primary key ([id])
)
go
insert into tasks([date],project_id,spent_time)
select '2012-04-02',1,10
union all select '2012-04-02',1,5
union all select '2012-04-02',2,5
union all select '2012-04-03',1,8
union all select '2012-04-03',2,1
go
正如上面的评论中所提到的,您需要动态生成SQL语句。我在变量@sql中执行此操作,然后在最后执行它。这是我的解决方案:
declare @sql nvarchar(4000), @project_id nvarchar(10)
select @sql = 'select [date]'
declare c cursor for select distinct convert(nvarchar(10),project_id) as project_id from tasks order by project_id
open c
fetch c into @project_id
while @@FETCH_STATUS = 0
begin
select @sql = @sql + ', sum(case when project_id = ' + @project_id + ' then spent_time else 0 end) as project_' + @project_id
fetch c into @project_id
end
close c
deallocate c
select @sql = @sql + ', sum(spent_time) as sum_of_projects from tasks group by [date] order by [date]'
exec (@sql)
根据我的测试数据的预期,它会生成输出:
date project_1 project_2
---- --------- ---------
2012-04-02 15 5
2012-04-03 8 1
希望这有帮助!
<强>更新强>
OP已经表示希望避免使用游标,因此以下代码也可以(至少在MS SQL Server上)不使用游标...declare @sql nvarchar(4000), @project_id nvarchar(10)
select @sql = 'select [date]'
select @sql = @sql + ', sum(case when project_id = ' + project_id + ' then spent_time else 0 end) as project_' + project_id
from (select distinct CONVERT(nvarchar(10), project_id) as project_id from tasks) q
select @sql = @sql + ', sum(spent_time) as sum_of_projects from tasks group by [date] order by [date]'
exec (@sql)
答案 1 :(得分:1)
您需要编写写入SQL的代码。没有办法让一个静态SQL查询返回动态数量的列。只有动态构建查询本身才能实现这一目标。
您的示例代码很好。对于固定数量的项目。
你甚至可以制作&#39; 6&#39;&#39; 41&#39;和&#39; 14&#39;进入参数,意味着您的查询将始终返回三个项目,但每次都可以是不同的项目。
但是要有第四个项目,您需要更改查询。
您可以编写代码来动态地进行更改(动态SQL),或者只是计算出您一次需要的大多数列,然后使用该限制。
答案 2 :(得分:0)