我有以下表格,其中包含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
我也不确定如何合并制造商总数。如何在同一查询中返回两个数据集?
答案 0 :(得分:6)
听起来你想要PIVOT
数据。这可以获得每个type
的总计,然后每个总计manufacturer
。 PIVOT
有两种静态或动态方式。
静态(见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)
两者都应该提供相同的结果。区别在于您必须对所需的值进行硬编码的静态版本。动态版本在运行时获取列的值,因此如果制造商更改它将自动调整。
答案 1 :(得分:1)
为什么这被贬低?这是一个有效的答案。问题似乎是希望不同行上的类型和制造商(它没有明确说明,但这是一个合理的解释)。没有评论的贬低肯定是不礼貌的。
您需要使用UNION执行此操作。一个提示是你的最终输出不适合你的问题。你没有制造商的地方。
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
答案 2 :(得分:0)
为什么需要它们在同一个数据集中?他们正在回答两个完全不同的问题,因此以任何方式组合它们都没有意义。如果可以将类型混合在一起,并且您希望TYPE列为TYPE / MANUFACTURER,那么它非常简单。如果您需要将类型放在列中,那么您可以将每个客户的所有内容放在一行中,然后按顺序排列。
如果您想要一个支点,请使用@ 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