-1

ループを使用して、計算に基づいて可変数の列を作成できますか?

テーブル A: ID、名前、日付、アイテムの列があります。誰が何日に商品を購入したかを示します。アイテムが購入されるたびに、名前が複数回表示されます。id は一意です。

テーブル B: 名前、開始日があります。名前がいつ機能し始めたかを示します。

(name を begindate に関連付ける方法は知っているので、以下の疑似コードには実際には含まれていません。)

表 C は、結果を次のようにしたいものです。

name   itemsday1 itemsday2 itemsday3... itemsdayn

2 番目の列は今日購入されたアイテムに対応し、最後の列は名前の開始日より前に購入されたアイテムに対応します。列の数は、最初に開始した人によって異なる必要があります。クエリをループして、begindate から今日までの毎日の列を作成し、その日に Name によって購入されたアイテムの数をカウントします。

疑似コード:

declare mostd INT
select datediff(dd, begindate, getdate()) as spans  into #span from B
set mostd = select max(spans) from #span

select
    name
    ,while mostd !=0
        begin
            case when???
                count(items)
            end as column.mostd
            mostd=mostd-1
        end
    end
from A (join B blah blah)
group by name

Results
NAME    column4    column3    column2    column1    column0
James   9          8          7          6          NULL
Wade    5          4          3          NULL       NULL
Bosh    2          1          NULL       NULL       NULL
Durant  0          9          8          NULL       NULL

TSQL はこれを行うことができますか? これを実際のコードに固めるのを手伝ってくれませんか? ありがとう。

4

3 に答える 3

0

これは PIVOT 演算子http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspxを使用して可能です

更新: 例。この素晴らしい記事に触発されています: http://dotnetgalactics.wordpress.com/2009/10/23/using-sql-server-20052008-pivot-on-unknown-number-of-columns-dynamic-pivot/ :

-- create table #items (id int, name varchar(40), date datetime, userid int)
-- create table #users (id int, name varchar(40), begindate datetime)

declare @dates varchar(4000)
declare @query varchar(4000)

SELECT  @dates = STUFF(( SELECT DISTINCT
                        '],[' + cast(date as varchar(30))
                        FROM    #items
                        ORDER BY '],[' + cast(date as varchar(30))
                        FOR XML PATH('')
                        ), 1, 2, '') + ']'

set @query = 'SELECT * FROM (SELECT #users.name, date FROM #items
        INNER JOIN #users ON #items.userid = #users.id) items 
        PIVOT (COUNT(date) FOR date IN (' + @dates + ')) pvt'

EXECUTE(@query)

結果:

name  2012-10-01 2012-10-02 2012-10-03 2012-10-04 2012-10-05 2012-10-06 2012-10-07

user1     0          0           1          0          0          1         0
user2     1          6           0          0          0          1         1
user3     1          1           7          0          0          3         0
user4     0          0           0          1          1          1         1
于 2012-06-12T18:53:33.743 に答える
0

これを行うには、動的 SQL を使用する必要があります。皮切りに

DECLARE @SelectSQL varchar(max) = "SELECT name";

次に、while ループを実行し、フィールド名の整数カウンターを追跡します (これを逆の順序で実行したい場合は、DATEDIFF(day, getdate(), begindate) を使用して逆方向にカウントする必要があります)。列で表す必要がある日ごとに、次のように出力します。

SELECT @SelectSQL = @SelectSQL + ', (SELECT COUNT(id) FROM TableA where name = TableB.name AND [date] = ''' + CONVERT(varchar, @mostd) + ''') AS column' + str(@ColumnCounter)

次に、ループの外側で、残りのクエリを後置します。

@SelectSQL = @SelectSQL + ' FROM TableB';

サブクエリですべて処理されるため、TableA への結合がないことに注意してください。また、同じ理由で、あなたは必要ありませんGROUP BY.

編集:おっと、最後の部分を忘れていました。

これを実行するには、次を実行します。

EXEC (@SelectSQL);
于 2012-06-12T18:55:08.370 に答える
0

動的なデータのピボットに関連する SO にはいくつかの回答があります。これは私が提供したものであり、知っておくと便利です。

順序値に基づくSQL Server 2008動的ピボット

XML PATH 演算子を使用すると、結果セットで適切な列名も得られます。

于 2012-06-12T20:45:01.570 に答える