SQL 服务器如何在没有 PIVOT 或 UNPIVOT 或聚合的情况下将行转置为列
SQL Server How To Transpose Rows To Columns, without PIVOT or UNPIVOT or Aggregation
编辑 1: 两种解决方案和 DUPE 链接都有效,但其中 none 保留了我想要的列顺序。所有解决方案都按字母顺序对结果列名进行排序。如果有人对此有解决方案,请在评论中post。
编辑 2: @taryn has posted this SQL Fiddle 在评论中,列也进行排序:)
我已经看到无数关于做这样的事情的答案,但 none 是我想要实现的目标。几乎所有都涉及进行聚合或分组。因此,在您急于将此标记为 DUPE 之前,请先完整阅读问题。
我要做的就是将行转置为列,原始结果集的列名成为新结果集第一列的行值。
这是我的数据的样子,以及我想如何将其转换/转置为。
我已经对其进行了颜色编码,以便您可以快速清楚地理解这一点。
在 excel 中,我会选择第一个 table,复制它,然后右键单击并将其粘贴为 选择性粘贴,然后选中 Transpose 复选框。
我已经尝试了 PIVOT
和 UNPIVOT
,但似乎都无法满足我的需求。我可能没有正确使用它,但我花了比我预期更多的时间来解决这个问题。
我已经创建了一个 SQL Fiddle,其中包含源 table、示例数据和我在这里期望的内容,因此您可以从这里开始 => http://www.sqlfiddle.com/#!18/56afd/10
这也是内联粘贴的代码。
IF OBJECT_ID ('dbo.Players') IS NOT NULL
DROP TABLE dbo.Players;
CREATE TABLE dbo.Players
(
PlayerID INT
, Win INT
, Defeat INT
, StandOff INT
, CONSTRAINT PK_Players PRIMARY KEY CLUSTERED (PlayerID) ON [PRIMARY]
);
INSERT INTO dbo.Players (PlayerID, Win, Defeat, StandOff)
VALUES
(1, 7, 6, 9),
(2, 12, 5, 0),
(3, 3, 11, 1);
这是预期的输出
SELECT * FROM dbo.Players;
-- Need to Transpose above results, into the following.
-- -------------------------------------------------------------------
-- | Stat_Type | Player_1 | Player_2 | Player_3 |
-- -------------------------------------------------------------------
-- | Win | 7 | 12 | 3 |
-- -------------------------------------------------------------------
-- | Defeat | 6 | 5 | 11 |
-- -------------------------------------------------------------------
-- | StandOff | 9 | 0 | 1 |
-- -------------------------------------------------------------------
-- Column Names become Row values for 1st column
-- PlayerId becomes column names
在SQL服务器中,我会做:
select v.outcome,
max(case when v.playerId = 1 then val end) as playerId_1,
max(case when v.playerId = 2 then val end) as playerId_2,
max(case when v.playerId = 3 then val end) as playerId_3
from players cross apply
(values (playerId, win, 'win', 1),
(playerId, defeat, 'defeat', 2),
(playerId, standoff, 'standoff', 3)
) v(playerId, val, outcome, ordering)
group by v.outcome
order by max(ordering);
Here 就是 SQL Fiddle.
你应该可以用 pivot
/unpivot
做同样的事情。如果您不知道完整的球员名单或结果,那么您将需要动态 SQL.
更新: Here's SQL Fiddle with custom sort order. Credit:
使用UNPIVOT/PIVOT
:
WITH unpiv AS (
SELECT PlayerId, col, value
FROM dbo.Players
UNPIVOT (VALUE FOR col IN (Win, Defeat, StandOff)) unpiv
)
SELECT col AS Stat_Type, [1] AS Player1, [2] AS Player2, [3] AS Player3
FROM unpiv
PIVOT (MAX(value) FOR PlayerId IN ([1], [2], [3])) piv
ORDER BY CASE col WHEN 'Win' THEN 1 WHEN 'Defeat' THEN 2 ELSE 3 END;
编辑 1: 两种解决方案和 DUPE 链接都有效,但其中 none 保留了我想要的列顺序。所有解决方案都按字母顺序对结果列名进行排序。如果有人对此有解决方案,请在评论中post。
编辑 2: @taryn has posted this SQL Fiddle 在评论中,列也进行排序:)
我已经看到无数关于做这样的事情的答案,但 none 是我想要实现的目标。几乎所有都涉及进行聚合或分组。因此,在您急于将此标记为 DUPE 之前,请先完整阅读问题。
我要做的就是将行转置为列,原始结果集的列名成为新结果集第一列的行值。
这是我的数据的样子,以及我想如何将其转换/转置为。
我已经对其进行了颜色编码,以便您可以快速清楚地理解这一点。
在 excel 中,我会选择第一个 table,复制它,然后右键单击并将其粘贴为 选择性粘贴,然后选中 Transpose 复选框。
我已经尝试了 PIVOT
和 UNPIVOT
,但似乎都无法满足我的需求。我可能没有正确使用它,但我花了比我预期更多的时间来解决这个问题。
我已经创建了一个 SQL Fiddle,其中包含源 table、示例数据和我在这里期望的内容,因此您可以从这里开始 => http://www.sqlfiddle.com/#!18/56afd/10
这也是内联粘贴的代码。
IF OBJECT_ID ('dbo.Players') IS NOT NULL
DROP TABLE dbo.Players;
CREATE TABLE dbo.Players
(
PlayerID INT
, Win INT
, Defeat INT
, StandOff INT
, CONSTRAINT PK_Players PRIMARY KEY CLUSTERED (PlayerID) ON [PRIMARY]
);
INSERT INTO dbo.Players (PlayerID, Win, Defeat, StandOff)
VALUES
(1, 7, 6, 9),
(2, 12, 5, 0),
(3, 3, 11, 1);
这是预期的输出
SELECT * FROM dbo.Players;
-- Need to Transpose above results, into the following.
-- -------------------------------------------------------------------
-- | Stat_Type | Player_1 | Player_2 | Player_3 |
-- -------------------------------------------------------------------
-- | Win | 7 | 12 | 3 |
-- -------------------------------------------------------------------
-- | Defeat | 6 | 5 | 11 |
-- -------------------------------------------------------------------
-- | StandOff | 9 | 0 | 1 |
-- -------------------------------------------------------------------
-- Column Names become Row values for 1st column
-- PlayerId becomes column names
在SQL服务器中,我会做:
select v.outcome,
max(case when v.playerId = 1 then val end) as playerId_1,
max(case when v.playerId = 2 then val end) as playerId_2,
max(case when v.playerId = 3 then val end) as playerId_3
from players cross apply
(values (playerId, win, 'win', 1),
(playerId, defeat, 'defeat', 2),
(playerId, standoff, 'standoff', 3)
) v(playerId, val, outcome, ordering)
group by v.outcome
order by max(ordering);
Here 就是 SQL Fiddle.
你应该可以用 pivot
/unpivot
做同样的事情。如果您不知道完整的球员名单或结果,那么您将需要动态 SQL.
更新: Here's SQL Fiddle with custom sort order. Credit:
使用UNPIVOT/PIVOT
:
WITH unpiv AS (
SELECT PlayerId, col, value
FROM dbo.Players
UNPIVOT (VALUE FOR col IN (Win, Defeat, StandOff)) unpiv
)
SELECT col AS Stat_Type, [1] AS Player1, [2] AS Player2, [3] AS Player3
FROM unpiv
PIVOT (MAX(value) FOR PlayerId IN ([1], [2], [3])) piv
ORDER BY CASE col WHEN 'Win' THEN 1 WHEN 'Defeat' THEN 2 ELSE 3 END;