0

これは SQL Server 2008 で実行されています。

とにかく、私は売上データを持っており、出力を次のように表示するクエリを作成できます。

id | Name       | Period  | Sales
1  | Customer X | 2013/01 | 50
1  | Customer X | 2013/02 | 45

現在、このデータを実行した後、最終的な出力が次のようになるように、コード ビハインドでデータを再配置しています。

id  | Name       | 2013/01 | 2013/02
1   | Customer X |   50    |   40

問題は次のとおりです。

  1. 日付 (YYYY/MM) の範囲は、ユーザーからの入力です。
  2. ユーザーがより多くの出力 (たとえば、住所、およびその顧客に関連する他の可能なフィールドなど) を選択すると、その情報がすべての行に複製されます。50000 人以上のユーザーに対して、5 年以上にわたって 1 行に 10 から 15 のアイテムを処理している場合、メモリ不足の問題が発生し、非効率的です。

必要なデータ (顧客 ID - 結合方法、期間、売上高) のみを取得し、その後、別のクエリを実行して追加データを取得することを検討しました。これは効率的とは思えませんが、可能性はあります。

私が最善の選択肢であると考えているもう1つの方法は、クエリを書き直して、現在のコードビハインドが行っていることを実行し、データを一緒にピボットして、顧客データが重複しないようにすることです。多くの不要なデータを移動していません。

私が取り組んでいるもののより良い例を示すために、これらのテーブルを想定してみましょう:

住所

id | HouseNum | Street | Unit | City | State

お客様

id | Name | 

販売

id | Period | Sales

したがって、これらのテーブルを顧客 ID で結合し、すべての住所データを表示し、ユーザーが「2012/01 -- 2012/12」と入力したと仮定すると、それを 2012/01、2012/02 に変換できます。 2012/12 を私のコード ビハインドで実行前にクエリに入力するので、それを利用できます。

私がそれをどのように見せたいかは次のようになります:

id | Name | HouseNum | Street   | City | State | 2012/01 | 2012/02 | ... | 2012/12
1  | X    | 100      | Main St. | ABC  | DEF   |   30    |         | ... |   20

(2012/02 のその顧客の販売データはありません -- データのいずれかが空白の場合、NULL ではなく空白の文字列 "" にしたい)

これを可能な限り最善の方法で説明していない可能性があることは承知していますので、お知らせください。さらに情報を追加します. ありがとうございました!

編集:ああ、最後にもう1つ。ピボットされたすべてのデータを合計する Min、Max、Avg、および Total 列を最後に追加することは可能でしょうか? コードビハインドでそれを行うことは大したことではありませんが、より多くのSQLサーバーが私のためにできることは、imo!

編集:もう1つ、期間は「2013/01」などの表にありますが、複雑すぎなければ「2013年1月」などに名前を変更したいと思いますか?

4

1 に答える 1

2

PIVOT 関数を実装して、データを行から列に変換できます。以下を使用して結果を取得できます。

select id,
  name,
  HouseNum,
  Street,
  City,
  State,
  isnull([2013/01], 0) [2013/01], 
  isnull([2013/02], 0) [2013/02], 
  isnull([2012/02], 0) [2012/02], 
  isnull([2012/12], 0) [2012/12],
  MinSales,
  MaxSales,
  AvgSales,
  TotalSales
from
(
  select c.id,
    c.name,
    a.HouseNum,
    a.Street,
    a.city,
    a.state,
    s.period,
    s.sales,
    min(s.sales) over(partition by c.id) MinSales,
    max(s.sales) over(partition by c.id) MaxSales,
    avg(s.sales) over(partition by c.id) AvgSales,
    sum(s.sales) over(partition by c.id) TotalSales
  from customer c
  inner join address a
    on c.id = a.id
  inner join sales s
    on c.id = s.id
) src
pivot
(
  sum(sales)
  for period in ([2013/01], [2013/02], [2012/02], [2012/12])
) piv;

SQL Fiddle with Demoを参照してください。

period列に変換したい値の数が不明な場合は、動的 SQL を使用して結果を取得する必要があります。

DECLARE @cols AS NVARCHAR(MAX),
    @colsNull AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(period) 
                    from Sales
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsNull = STUFF((SELECT distinct ', IsNull(' + QUOTENAME(period) + ', 0) as '+ QUOTENAME(period) 
                    from Sales
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT id,
                name,
                HouseNum,
                Street,
                City,
                State,' + @colsNull + ' ,
                MinSales,
                MaxSales,
                AvgSales,
                TotalSales
             from 
             (
               select c.id,
                c.name,
                a.HouseNum,
                a.Street,
                a.city,
                a.state,
                s.period,
                s.sales,
                min(s.sales) over(partition by c.id) MinSales,
                max(s.sales) over(partition by c.id) MaxSales,
                avg(s.sales) over(partition by c.id) AvgSales,
                sum(s.sales) over(partition by c.id) TotalSales
              from customer c
              inner join address a
                on c.id = a.id
              inner join sales s
                on c.id = s.id
            ) x
            pivot 
            (
                sum(sales)
                for period in (' + @cols + ')
            ) p '

execute(@query)

SQL Fiddle with Demoを参照してください。これらは結果を与えます:

| ID |       NAME | HOUSENUM |    STREET |    CITY |  STATE | 2012/02 | 2012/12 | 2013/01 | 2013/02 | MINSALES | MAXSALES | AVGSALES | TOTALSALES |
---------------------------------------------------------------------------------------------------------------------------------------------------
|  1 | Customer X |      100 | Maint St. |     ABC |    DEF |       0 |      20 |      50 |      45 |       20 |       50 |       38 |        115 |
|  2 | Customer Y |      108 |   Lost Rd | Unknown | Island |      10 |       0 |       0 |       0 |       10 |       10 |       10 |         10 |
于 2013-04-19T20:17:31.373 に答える