我有以下内容:
customerID | OrderID | OrderPosition | Articlenumber|
-----------+---------+---------------+--------------+
101 | 1 | 1 | 123 |
101 | 1 | 2 | 799 |
102 | 2 | 1 | 111 |
103 | 3 | 1 | 456 |
101 | 4 | 1 | 789 |
103 | 5 | 1 | 444 |
103 | 5 | 2 | 999 |
101 | 6 | 1 | 555 |
101 | 6 | 2 | 777 |
101 | 6 | 3 | 222 |
并且我想要以下内容(每个客户ID最多汇总4篇文章(按orderID(从高到低排序)和OrderPosition(从低到低)排序):
customerID |articelnumber 1|articelnumber 2|articelnumber 3|articelnumber 4|
-------+-------------------+---------------+---------------+---------------+
101 |555 |777 |222 | 789 |
102 |111 |NULL |NULL |NULL |
103 |444 |999 |456 |NULL |
像这样尝试过,但这不能正常工作:
select *
from
(
select customerid, OrderID , OrderPosition, Articlenumber FROM table
) src
pivot
(
avg (Articlenumber)
for OrderPosition in ([articelnumber 1], [articelnumber 2], [articelnumber 3], [articelnumber 4])
) piv
答案 0 :(得分:1)
我花了一些时间才能获得与您期望的输出相同的结果,但最终我设法做到了:
if exists (select 1 from sysobjects where name = 'TempTable')
drop table TempTable;
if exists (select 1 from sysobjects where name = 'TempTable2')
drop table TempTable2;
declare @cols nvarchar(max)
, @cols2 nvarchar(max)
, @sql nvarchar(max)
, @loop int;
create table TempTable (id int primary key identity, CustomerID int, OrderID int, OrderPosition int, ArticleNumber int)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,1,1,123)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,1,2,799)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (102,2,1,111)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (103,3,1,456)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,4,1,789)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (103,5,1,444)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (103,5,2,999)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,6,1,555)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,6,2,777)
insert into TempTable (CustomerID, OrderID, OrderPosition, ArticleNumber) values (101,6,3,222);
create table TempTable2 (CustomerID int, OrderID int, OrderPosition int, ArticleNumber int, ArticleDesc varchar(100))
select @loop = min(id) from TempTable
while @loop is not null
begin
set @sql = ' insert into TempTable2 (CustomerID, OrderID, OrderPosition, ArticleNumber, ArticleDesc)
select top 4 CustomerID, OrderID, OrderPosition, ArticleNumber, ''ArticleNumber ''+cast(rank() over (order by orderID desc, OrderPosition)as varchar)
from TempTable where CustomerID = '+cast((select CustomerID from TempTable where id = @loop) as varchar)+
'order by orderID desc, OrderPosition'
exec (@sql)
select @loop = min(id) from TempTable where id > @loop
end
select
CustomerID
, sum(isnull([ArticleNumber 1],0)) [ArticleNumber 1]
, sum(isnull([ArticleNumber 2],0)) [ArticleNumber 2]
, sum(isnull([ArticleNumber 3],0)) [ArticleNumber 3]
, sum(isnull([ArticleNumber 4],0)) [ArticleNumber 4]
from
(
select
CustomerID, OrderID, OrderPosition, ArticleDesc, ArticleNumber
from TempTable2
group by CustomerID, OrderID, OrderPosition, ArticleDesc, ArticleNumber
) d
pivot
(sum(ArticleNumber) for ArticleDesc in ([ArticleNumber 1],[ArticleNumber 2],[ArticleNumber 3],[ArticleNumber 4])
) p
group by CustomerID
我的答案可能不是以上天才们回答的最好,但我仍然得到相同的结果...
答案 1 :(得分:0)
修改后的示例数据可满足您的需求
IF OBJECT_ID('tempdb..#TEMP ')IS NOT NULL
DROP TABLE #TEMP
;WITH CTE(customerID , OrderID , OrderPosition , Articlenumber)
AS
(
SELECT 101, 1 , 1 , 123 UNION ALL
SELECT 101, 1 , 2 , 799 UNION ALL
SELECT 102, 2 , 1 , 111 UNION ALL
SELECT 103, 3 , 1 , 456 UNION ALL
SELECT 101, 4 , 1 , 789 UNION ALL
SELECT 103, 5 , 1 , 444 UNION ALL
SELECT 103, 5 , 2 , 999 UNION ALL
SELECT 101, 6 , 1 , 555 UNION ALL
SELECT 101, 6 , 2 , 777 UNION ALL
SELECT 101, 6 , 3 , 222
)
SELECT * , SUM(ArticleNumber)OVER(PARTITION BY customerID ORDER BY customerID ) AS SumOfArticlePerCustomer
INTO #TEMP
FROM
(
SELECT * ,
ROW_NUMBER()OVER(PARTITION BY customerID ORDER BY OrderID DESC ) RNk,
'ArticleNumber_'+CAST(ROW_NUMBER()OVER(PARTITION BY customerID ORDER BY OrderID DESC ) AS VARCHAR(10)) AS ArticleNumberData
FROM CTE
)DT
WHERE RNk <= 4
SELECT * FROM #TEMP
动态Sql,用于动态生成列并达到预期结果
DECLARE @Sql nvarchar(max),
@DynamicColumn nvarchar(max),
@MaxDynamicColumn nvarchar(max)
SELECT @DynamicColumn = STUFF((SELECT DISTINCT', '+QUOTENAME(ArticleNumberData )
FROM #TEMP FOR XML PATH ('')),1,1,'')
SELECT @MaxDynamicColumn = STUFF((SELECT DISTINCT', '+'MAX('+QUOTENAME(ArticleNumberData )+') AS '+QUOTENAME(ArticleNumberData )+CHAR(13)+CHAR(10)
FROM #TEMP FOR XML PATH (''),TYPE).value('text()[1]','nvarchar(max)'),1,1,N'')
SET @Sql='SELECT CustomerID,'+ @MaxDynamicColumn+',SumOfArticlePerCustomer
FROM
(
SELECT *
FROM #TEMP
)AS src
PIVOT
(
MAX(Articlenumber) FOR [ArticleNumberData] IN ('+@DynamicColumn+')
) AS Pvt
GROUP BY customerID,SumOfArticlePerCustomer
ORDER BY CustomerID'
EXEC (@Sql)
PRINT @Sql
答案 2 :(得分:0)
如果仅需四列,并且输出的结果与上面列出的相同,则始终可以使用ROW_NUMBER
,CTE和一些联接:
;with TopFour
as
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY [customerID] ORDER BY orderID DESC, OrderPosition ASC) as [TheOrder]
FROM [table]
)
SELECT
a.[customerID],
a.[Articlenumber] as [articlenumber 1],
b.[Articlenumber] as [articlenumber 2],
c.[Articlenumber] as [articlenumber 3],
d.[Articlenumber] as [articlenumber 4]
FROM
TopFour a
LEFT JOIN
TopFour b
ON
a.customerID = b.customerID
AND
b.TheOrder = 2
LEFT JOIN
TopFour c
ON
a.customerID = c.customerID
AND
c.TheOrder = 3
LEFT JOIN
TopFour d
ON
a.customerID = d.customerID
AND
d.TheOrder = 4
WHERE
a.TheOrder = 1