0

SQL Server 2008 R2 の顧客データと購入データを含む次のテーブルがあります。

お客様

CustId   Last    First    Phone
   1     Doe     John    555-5555  
   2     Smith   Sally   444-4444
   3     Smith   Greg    222-1212

Order_Header

OrderId  CustId  Date  
 1001       3   07/08/2011
 1002       2   07/19/2011
 1003       2   03/12/2012
 1004       1   03/14/2012
 1005       3   03/20/2012
 1006       1   04/17/2012
 1007       2   06/04/2012
 1008       1   08/04/2011

Order_Lines

OrderId     Sequence    Item      Type    Manufacturer   Price
 1001          1        WIDGET     C         WidgCo      12.00
 1001          2        SWITCH     C        SwitchCo     10.00
 1002          1        RADIO      A        RadSupply    30.00
 1002          2        CRT        A        CRT&More     31.00
 1002          3        NCARD      G        iNetwork      5.00
 1003          1        SENSOR     E        Sensora       7.50
 1004          1        SENSOR     D        Sensora       6.00
 1005          1        WIDGET     C         WidgInc     11.50
 1006          1        RADIO      A        RadSupply    30.00
 1006          2        SCREEN     A        ScreensInc    2.00
 1007          1        ANTENNA    G       AntennasPlus   5.50
 1008          1        SWITCH     B       SwitchOutlet   6.00

各顧客、連絡先情報、各タイプに費やした合計、および各メーカーに費やした合計をリストするクエリを作成しようとしています。これまで、さまざまな JOINS を試してきましたが、うまく動作しないようです。
私はこのようなものを返すことを目指しています:

CustomerId  Last  First  Phone     TYPE  TOT_TYPE  
   1        Doe   John  555-5555    A      32.00
   1        Doe   John  555-5555    B      6.00  
   1        Doe   John  555-5555    D      6.00    

また、メーカーの合計を組み込む方法もわかりません。同じクエリで両方のデータセットを返すにはどうすればよいですか?

4

3 に答える 3

6

データにしたいように聞こえPIVOTます。typeこれにより、それぞれの合計を取得し、次に各合計を で取得できますmanufacturerPIVOT静的または動的の 2 つの方法があります。

静的 ( SQL Fiddle with Demoを参照)

SELECT custid, last, first, phone, type,
    IsNull([AntennaPlus], 0) as [AntennaPlus],
    IsNull([CRT&More], 0) as [CRT&More],
    IsNull([iNetwork], 0) as [iNetwork],
    IsNull([RadSupply], 0) as [RadSupply],
    IsNull([ScreensInc], 0) as [ScreensInc],
    IsNull([Sensora], 0) as [Sensora],
    IsNull([SwitchCo], 0) as [SwitchCo],
    IsNull([SwitchOutlet], 0) as [SwitchOutlet],
    IsNull([WidgCo], 0) as [WidgCo],  
    IsNull([AntennaPlus], 0)+ 
    IsNull([CRT&More], 0)+ 
    IsNull([iNetwork], 0)+ 
    IsNull([RadSupply], 0)+ 
    IsNull([ScreensInc], 0)+ 
    IsNull([Sensora], 0)+ 
    IsNull([SwitchCo], 0)+ 
    IsNull([SwitchOutlet], 0)+ 
    IsNull([WidgCo], 0) Total 
from 
 (
    SELECT c.custid, c.last, c.first, c.phone,
        ol1.type, 
        ol1.manufacturer,
        ol1.price
    from customers c
    inner join Order_Header oh
        on c.custid = oh.custid
    inner join Order_Lines ol1
        on oh.orderid = ol1.orderid
 ) x
 pivot 
 (
    sum(price)
    for manufacturer in ( [AntennaPlus], [CRT&More], [iNetwork], [RadSupply], [ScreensInc], [Sensora], [SwitchCo], [SwitchOutlet], [WidgCo])
 ) p 

動的ピボット ( SQL Fiddle with Demoを参照)

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX),
    @colsPivot AS NVARCHAR(MAX),
    @colsTotal AS NVARCHAR(MAX)

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

select @colsPivot = STUFF((SELECT distinct ',IsNull(' + QUOTENAME(manufacturer)+', 0) as ['+ manufacturer+ ']'
                    from Order_Lines
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsTotal = STUFF((SELECT distinct '+ IsNull(' + QUOTENAME(manufacturer)+', 0)'
                    from Order_Lines
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query 
      = 'SELECT custid, last, first, phone, type,' + @colsPivot + ', '+ @colsTotal+' Total from 
         (
            SELECT c.custid, c.last, c.first, c.phone,
                ol1.type, 
                ol1.manufacturer,
                ol1.price
            from customers c
            inner join Order_Header oh
                on c.custid = oh.custid
            inner join Order_Lines ol1
                on oh.orderid = ol1.orderid
         ) x
         pivot 
         (
            sum(price)
            for manufacturer in (' + @cols + ')
         ) p '
execute(@query)

どちらも同じ結果になるはずです。違いは、必要な値をハードコーディングする必要がある静的バージョンです。動的バージョンは実行時に列の値を取得するため、メーカーが変更された場合は自動的に調整されます。

于 2012-08-20T17:30:34.320 に答える
1

なぜこれが反対票を投じられているのですか?質問に対する有効な回答です。質問は、タイプとメーカーを別の行に表示する必要があるようです (明示的には言いませんが、妥当な解釈です)。コメントなしでのマイナス投票は間違いなく失礼です。

UNION でこれを行う必要があります。ヒントの 1 つは、最終的な出力が質問に合わないことです。メーカーの居場所はありません。

select CustomerId, Last, First, Phone,
       Type, Manufacturer, TotPrice
from Customers C join
     ((select customerId, Type, NULL as Manufacturer, sum(Price) as TotPrice,
       from Order_Header oh join
            Order o
            on oh.OrderId = o.OrderId
       group by  customerId, Type
      ) union all
      ((select customerId, NULL as Type, Manufacturer, sum(Price) as TotPrice,
       from Order_Header oh join
            Order o
            on oh.OrderId = o.OrderId
       group by  customerId, Manufacturer
      )
     ) s
     on s.CustomerId = s.CustomerId
于 2012-08-20T16:07:32.393 に答える
0

それらを同じデータセットに含める必要があるのはなぜですか? 彼らは 2 つのまったく異なる質問に答えているので、それらをどのように組み合わせても意味がありません。タイプを混在させても問題がなく、TYPE 列を TYPE/MANUFACTURER にしたい場合は、非常に簡単です。各顧客のすべてを 1 つの行に配置できるように、タイプを列に配置する必要がある場合は、ピボットが適切です。

ピボットが必要な場合は、@bluefeet のソリューションを使用してください。それ以外の場合は、これまたはゴードンのバージョンを検討できます。これはより良いパフォーマンスを発揮すると思いますが、テストは順調です。

SELECT
   C.DesiredColumns,
   P.Category,
   P.Item
   P.TotalPrice
FROM
   dbo.Customers C
   INNER JOIN (
      SELECT
         H.CustomerId,
         V.Category,
         V.Item,
         Sum(L.Price) TotalPrice
      FROM
         dbo.Order_Header H
         INNER JOIN dbo.Order_Lines L
            ON H.OrderId = L.OrderId
         CROSS APPLY (
            VALUES
               ('Type', [Type]),
               ('Mfr', Manufacturer)
         ) V (Category, Item)
      GROUP BY
         H.CustomerId
         V.Category,
         V.Item
   ) P ON C.CustomerId = P.CustomerId
于 2012-08-21T01:33:03.900 に答える