3

一部のアプリケーションでは、次の 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 の合計を示す追加の列が 1 つ必要です。

したがって、結果の構造は DATE、PROJECT_1、PROJECT_2、PROJECT_3、SUM_OF_PROJECTS になります。

行が存在しないデータも取得できますか? たとえば2012-04-03、次の例では、カレンダー テーブルを使用しないことをお勧めします

任意のポインタをいただければ幸いです。

その他の詳細: データベース - mysql、Rails(2.3.14)

4

3 に答える 3

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)
于 2012-04-26T10:54:15.327 に答える
1

SQL を書き込むコードを記述する必要があります。動的な数の列を返す単一の静的 SQL クエリを持つ方法はありません。クエリ自体を動的に構築することによってのみ、それを実現できます。

サンプルコードは問題ありません。固定数のプロジェクトの場合。

'6'、'41'、'14' をパラメーターにすることもできます。つまり、クエリは常に 3 つのプロジェクトを返しますが、毎回異なるプロジェクトになる可能性があります。

しかし、4 つ目のプロジェクトを作成するには、クエリを変更する必要があります。

その場でその変更を行うコードを作成することも (動的 SQL)、必要な列を一度に処理して、その制限を受け入れることもできます。

于 2012-04-26T10:52:52.543 に答える
0

ピボットを使用してみることができます。例については、http://blogs.msdn.com/b/spike/archive/2009/03/03/pivot-tables-in-sql-server-a-simple-sample.aspxを確認してください

于 2012-04-26T10:45:22.457 に答える