sql 服务器数据透视表 2 值
sql server pivot 2 values
我正在尝试将 2 个值放入一行。
示例数据:
recipeID componentID count
9 21 5
12 3 1
12 30 1
12 34 1
12 96 1
27 29 1
27 43 1
28 29 1
28 44 1
我尝试了 2 个枢轴,但我得到了
recipeID 1 2 3 4 11 12 13 14
9 21 NULL NULL NULL 5 NULL NULL NULL
12 NULL NULL NULL 96 NULL NULL NULL 1
12 NULL NULL 34 NULL NULL NULL 1 NULL
12 NULL 30 NULL NULL NULL 1 NULL NULL
12 3 NULL NULL NULL 1 NULL NULL NULL
27 NULL 43 NULL NULL NULL 1 NULL NULL
27 29 NULL NULL NULL 1 NULL NULL NULL
28 NULL 44 NULL NULL NULL 1 NULL NULL
28 29 NULL NULL NULL 1 NULL NULL NULL
我希望什么时候:
recipeID 1 2 3 4 11 12 13 14
9 21 NULL NULL NULL 5 NULL NULL NULL
12 3 30 34 96 1 1 1 1
27 29 43 NULL NULL 1 1 NULL NULL
28 29 44 NULL NULL 1 1 NULL NULL
有什么想法吗?
当前代码是:
select * from (
SELECT [recipeID]
,[componentID]
,[count]
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID) rn
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID)+10 rn10
FROM [Recipe_Ingredients] ri_ ) as ri
PIVOT
(
sum([componentID])
for rn in ([1],[2],[3],[4])) as pvt
PIVOT
(
sum([count])
for rn10 in ([11],[12],[13],[14])) as pvt10
像往常一样在外部查询的列上使用聚合函数(sum 或 max)和 group by
:
SELECT
recipeID
, SUM([1]) [1]
, SUM([2]) [2]
, SUM([3]) [3]
, SUM([4]) [4]
, SUM([11]) [11]
, SUM([12]) [12]
, SUM([13]) [13]
, SUM([14]) [14]
FROM (
SELECT [recipeID]
,[componentID]
,[count]
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID) rn
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID)+10 rn10
FROM [Recipe_Ingredients] ri_ ) as ri
PIVOT
(
sum([componentID])
for rn in ([1],[2],[3],[4])) as pvt
PIVOT
(
sum([count])
for rn10 in ([11],[12],[13],[14])) as pvt10
GROUP BY recipeID;
| recipeID | 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 |
|----------|----|--------|--------|--------|----|--------|--------|--------|
| 9 | 21 | (null) | (null) | (null) | 5 | (null) | (null) | (null) |
| 12 | 3 | 30 | 34 | 96 | 1 | 1 | 1 | 1 |
| 27 | 29 | 43 | (null) | (null) | 1 | 1 | (null) | (null) |
| 28 | 29 | 44 | (null) | (null) | 1 | 1 | (null) | (null) |
这可以发挥魔力。
select recipeID,
MAX([1]) AS '1',
MAX([2]) AS '2',
MAX([3]) AS '3',
MAX([4]) AS '4',
MAX([11]) AS '11',
MAX([12]) AS '12',
MAX([13]) AS '13',
MAX([14]) AS '14'
from (
SELECT [recipeID]
,[componentID]
,[count]
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID) rn
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID) + 10 rn10
FROM [Recipe_Ingredients] ri_ ) as ri
PIVOT
(
sum([componentID])
for rn in ([1],[2],[3],[4])) as pvt
PIVOT
(
sum([count])
for rn10 in ([11],[12],[13],[14])) as pvt10
GROUP BY recipeId
这里有一个Fiddler
希望对您有所帮助
另一种方法是将每个枢轴作为子选择,然后将它们合并在一起:
SELECT Pivot1.recipeID ,
Pivot1.[1] ,
Pivot1.[2] ,
Pivot1.[3] ,
Pivot1.[4] ,
Pivot2.[11] ,
Pivot2.[12] ,
Pivot2.[13] ,
Pivot2.[14]
FROM ( SELECT *
FROM ( SELECT [recipeID] ,
[componentID] ,
ROW_NUMBER() OVER ( PARTITION BY [recipeID] ORDER BY componentID ) rn
FROM [Recipe_Ingredients] ri_
) AS ri PIVOT
( SUM([componentID]) FOR rn IN ( [1], [2], [3], [4] ) ) AS pvt
) Pivot1
INNER JOIN ( SELECT *
FROM ( SELECT [recipeID] ,
[count] ,
ROW_NUMBER() OVER ( PARTITION BY [recipeID] ORDER BY componentID )
+ 10 rn10
FROM [Recipe_Ingredients] ri_
) AS ri PIVOT
( SUM([count]) FOR rn10 IN ( [11], [12], [13], [14] ) ) AS pvt10
) Pivot2 ON Pivot2.recipeID = Pivot1.recipeID
发生这种情况是因为 PIVOT 函数处理了被透视的 table 中的所有字段。我在 blog post here.
中用一个例子解释了这一点
这是另一个使用动态交叉表的解决方案:
DECLARE @sql1 VARCHAR(2000) = '',
@sql2 VARCHAR(2000) = '',
@sql3 VARCHAR(2000) = ''
SELECT @sql1 =
'SELECT
recipeID' + CHAR(10)
SELECT @sql2 = @sql2 +
' , MAX(CASE WHEN RN = ' + CONVERT(VARCHAR(3), RN) + ' THEN componentID END) AS ' + QUOTENAME(RN) + CHAR(10)
FROM(
SELECT DISTINCT RN = ROW_NUMBER() OVER(PARTITION BY recipeID ORDER BY componentID)
FROM tbl
)b
SELECT @sql2 = @sql2 +
' , MAX(CASE WHEN RN = ' + CONVERT(VARCHAR(3), RN + 10) + ' THEN [count] END) AS ' + QUOTENAME(RN) + CHAR(10)
FROM(
SELECT DISTINCT RN = ROW_NUMBER() OVER(PARTITION BY recipeID ORDER BY componentID)
FROM tbl
)b
SELECT @sql3 =
'FROM(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY recipeID ORDER BY componentID)
FROM tbl
)t
GROUP BY recipeID'
PRINT (@sql1 + @sql2 + @sql3)
EXEC (@sql1 + @sql2 + @sql3)
结果
recipeID 1 2 3 4 11 12 13 14
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
9 21 NULL NULL NULL 5 NULL NULL NULL
12 3 30 34 96 1 1 1 1
27 29 43 NULL NULL 1 1 NULL NULL
28 29 44 NULL NULL 1 1 NULL NULL
我正在尝试将 2 个值放入一行。
示例数据:
recipeID componentID count
9 21 5
12 3 1
12 30 1
12 34 1
12 96 1
27 29 1
27 43 1
28 29 1
28 44 1
我尝试了 2 个枢轴,但我得到了
recipeID 1 2 3 4 11 12 13 14 9 21 NULL NULL NULL 5 NULL NULL NULL 12 NULL NULL NULL 96 NULL NULL NULL 1 12 NULL NULL 34 NULL NULL NULL 1 NULL 12 NULL 30 NULL NULL NULL 1 NULL NULL 12 3 NULL NULL NULL 1 NULL NULL NULL 27 NULL 43 NULL NULL NULL 1 NULL NULL 27 29 NULL NULL NULL 1 NULL NULL NULL 28 NULL 44 NULL NULL NULL 1 NULL NULL 28 29 NULL NULL NULL 1 NULL NULL NULL
我希望什么时候:
recipeID 1 2 3 4 11 12 13 14 9 21 NULL NULL NULL 5 NULL NULL NULL 12 3 30 34 96 1 1 1 1 27 29 43 NULL NULL 1 1 NULL NULL 28 29 44 NULL NULL 1 1 NULL NULL
有什么想法吗?
当前代码是:
select * from (
SELECT [recipeID]
,[componentID]
,[count]
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID) rn
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID)+10 rn10
FROM [Recipe_Ingredients] ri_ ) as ri
PIVOT
(
sum([componentID])
for rn in ([1],[2],[3],[4])) as pvt
PIVOT
(
sum([count])
for rn10 in ([11],[12],[13],[14])) as pvt10
像往常一样在外部查询的列上使用聚合函数(sum 或 max)和 group by
:
SELECT
recipeID
, SUM([1]) [1]
, SUM([2]) [2]
, SUM([3]) [3]
, SUM([4]) [4]
, SUM([11]) [11]
, SUM([12]) [12]
, SUM([13]) [13]
, SUM([14]) [14]
FROM (
SELECT [recipeID]
,[componentID]
,[count]
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID) rn
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID)+10 rn10
FROM [Recipe_Ingredients] ri_ ) as ri
PIVOT
(
sum([componentID])
for rn in ([1],[2],[3],[4])) as pvt
PIVOT
(
sum([count])
for rn10 in ([11],[12],[13],[14])) as pvt10
GROUP BY recipeID;
| recipeID | 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 |
|----------|----|--------|--------|--------|----|--------|--------|--------|
| 9 | 21 | (null) | (null) | (null) | 5 | (null) | (null) | (null) |
| 12 | 3 | 30 | 34 | 96 | 1 | 1 | 1 | 1 |
| 27 | 29 | 43 | (null) | (null) | 1 | 1 | (null) | (null) |
| 28 | 29 | 44 | (null) | (null) | 1 | 1 | (null) | (null) |
这可以发挥魔力。
select recipeID,
MAX([1]) AS '1',
MAX([2]) AS '2',
MAX([3]) AS '3',
MAX([4]) AS '4',
MAX([11]) AS '11',
MAX([12]) AS '12',
MAX([13]) AS '13',
MAX([14]) AS '14'
from (
SELECT [recipeID]
,[componentID]
,[count]
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID) rn
,ROW_NUMBER() over(partition by [recipeID] order by ComponentID) + 10 rn10
FROM [Recipe_Ingredients] ri_ ) as ri
PIVOT
(
sum([componentID])
for rn in ([1],[2],[3],[4])) as pvt
PIVOT
(
sum([count])
for rn10 in ([11],[12],[13],[14])) as pvt10
GROUP BY recipeId
这里有一个Fiddler
希望对您有所帮助
另一种方法是将每个枢轴作为子选择,然后将它们合并在一起:
SELECT Pivot1.recipeID ,
Pivot1.[1] ,
Pivot1.[2] ,
Pivot1.[3] ,
Pivot1.[4] ,
Pivot2.[11] ,
Pivot2.[12] ,
Pivot2.[13] ,
Pivot2.[14]
FROM ( SELECT *
FROM ( SELECT [recipeID] ,
[componentID] ,
ROW_NUMBER() OVER ( PARTITION BY [recipeID] ORDER BY componentID ) rn
FROM [Recipe_Ingredients] ri_
) AS ri PIVOT
( SUM([componentID]) FOR rn IN ( [1], [2], [3], [4] ) ) AS pvt
) Pivot1
INNER JOIN ( SELECT *
FROM ( SELECT [recipeID] ,
[count] ,
ROW_NUMBER() OVER ( PARTITION BY [recipeID] ORDER BY componentID )
+ 10 rn10
FROM [Recipe_Ingredients] ri_
) AS ri PIVOT
( SUM([count]) FOR rn10 IN ( [11], [12], [13], [14] ) ) AS pvt10
) Pivot2 ON Pivot2.recipeID = Pivot1.recipeID
发生这种情况是因为 PIVOT 函数处理了被透视的 table 中的所有字段。我在 blog post here.
中用一个例子解释了这一点这是另一个使用动态交叉表的解决方案:
DECLARE @sql1 VARCHAR(2000) = '',
@sql2 VARCHAR(2000) = '',
@sql3 VARCHAR(2000) = ''
SELECT @sql1 =
'SELECT
recipeID' + CHAR(10)
SELECT @sql2 = @sql2 +
' , MAX(CASE WHEN RN = ' + CONVERT(VARCHAR(3), RN) + ' THEN componentID END) AS ' + QUOTENAME(RN) + CHAR(10)
FROM(
SELECT DISTINCT RN = ROW_NUMBER() OVER(PARTITION BY recipeID ORDER BY componentID)
FROM tbl
)b
SELECT @sql2 = @sql2 +
' , MAX(CASE WHEN RN = ' + CONVERT(VARCHAR(3), RN + 10) + ' THEN [count] END) AS ' + QUOTENAME(RN) + CHAR(10)
FROM(
SELECT DISTINCT RN = ROW_NUMBER() OVER(PARTITION BY recipeID ORDER BY componentID)
FROM tbl
)b
SELECT @sql3 =
'FROM(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY recipeID ORDER BY componentID)
FROM tbl
)t
GROUP BY recipeID'
PRINT (@sql1 + @sql2 + @sql3)
EXEC (@sql1 + @sql2 + @sql3)
结果
recipeID 1 2 3 4 11 12 13 14
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
9 21 NULL NULL NULL 5 NULL NULL NULL
12 3 30 34 96 1 1 1 1
27 29 43 NULL NULL 1 1 NULL NULL
28 29 44 NULL NULL 1 1 NULL NULL