SQL Server以及如何将行转换为列
我想使用SQL Server将列转换为行。我已经尝试过unpivot,但我没有足够的知识来制作它,只能制作一个专栏 这是原始表的脚本:SQL Server以及如何将行转换为列,sql,sql-server,unpivot,Sql,Sql Server,Unpivot,我想使用SQL Server将列转换为行。我已经尝试过unpivot,但我没有足够的知识来制作它,只能制作一个专栏 这是原始表的脚本: CREATE TABLE #tb1( [item] [numeric](6, 0) NULL, [class] [char](9) NULL, [P_1YEAR] [numeric](5, 0) NULL, [P_2YEAR] [numeric](5, 0) NULL, [P_3YEAR] [numeric](5, 0)
CREATE TABLE #tb1(
[item] [numeric](6, 0) NULL,
[class] [char](9) NULL,
[P_1YEAR] [numeric](5, 0) NULL,
[P_2YEAR] [numeric](5, 0) NULL,
[P_3YEAR] [numeric](5, 0) NULL,
[C_YR_RET1] [numeric](8, 4) NULL,
[C_YR_RET2] [numeric](8, 4) NULL,
[C_YR_RET3] [numeric](7, 4) NULL,
) ON [PRIMARY]
GO
INSERT #tb1 ( [item], [class], [P_1YEAR], [P_2YEAR], [P_3YEAR], [C_YR_RET1], [C_YR_RET2], [C_YR_RET3])
VALUES ( CAST(29 AS Numeric(6, 0)), N'A ', CAST(2018 AS Numeric(5, 0)), CAST(2017 AS Numeric(5, 0)), CAST(2016 AS Numeric(5, 0)),CAST(-7.0755 AS Numeric(8, 4)), CAST(6.0703 AS Numeric(8, 4)), CAST(13.3893 AS Numeric(7, 4)))
INSERT #tb1 ( [item], [class], [P_1YEAR], [P_2YEAR], [P_3YEAR], [C_YR_RET1], [C_YR_RET2], [C_YR_RET3])
VALUES (CAST(29 AS Numeric(6, 0)), N'F ', CAST(2018 AS Numeric(5, 0)), CAST(2017 AS Numeric(5, 0)), CAST(2016 AS Numeric(5, 0)), CAST(-6.0276 AS Numeric(8, 4)), CAST(7.2750 AS Numeric(8, 4)), CAST(14.8798 AS Numeric(7, 4)))
GO
最后一个表应该如下所示:
谢谢 一种方法是
SELECT
ITEM,
YEAR,
SUM(CASE WHEN CLASS='A' THEN C_YR_RET_1YR ELSE 0 /* OR NULL */ END) AS A,
SUM(CASE WHEN CLASS='F' THEN C_YR_RET_12YR ELSE 0 /* OR NULL*/ END) AS F
FROM
TABLE_NAME
GROUP BY
ITEM,
YEAR
您可能希望使用null或0,这取决于您以后是否决定在同一字段上使用聚合函数。零将使求和更容易。空值将使平均值变得更容易。一种方法是
SELECT
ITEM,
YEAR,
SUM(CASE WHEN CLASS='A' THEN C_YR_RET_1YR ELSE 0 /* OR NULL */ END) AS A,
SUM(CASE WHEN CLASS='F' THEN C_YR_RET_12YR ELSE 0 /* OR NULL*/ END) AS F
FROM
TABLE_NAME
GROUP BY
ITEM,
YEAR
您可能希望使用null或0,这取决于您以后是否决定在同一字段上使用聚合函数。零将使求和更容易。空值将使平均值变得更容易。试试这个-
SELECT item, [Year],
SUM(A) A,SUM(F) F
FROM
(
SELECT item, p_1year [Year],
CASE WHEN class = 'A' THEN c_yr_rate_1year ELSE 0 END 'A',
CASE WHEN class = 'F' THEN c_yr_rate_1year ELSE 0 END 'F'
FROM your_table
UNION ALL
SELECT item, p_2year [Year],
CASE WHEN class = 'A' THEN c_yr_rate_2year ELSE 0 END 'A',
CASE WHEN class = 'F' THEN c_yr_rate_2year ELSE 0 END 'F'
FROM your_table
UNION ALL
SELECT item, p_3year [Year],
CASE WHEN class = 'A' THEN c_yr_rate_3year ELSE 0 END 'A',
CASE WHEN class = 'F' THEN c_yr_rate_3year ELSE 0 END 'F'
FROM your_table
)A
GROUP BY item, [Year]
ORDER BY 2
试试这个-
SELECT item, [Year],
SUM(A) A,SUM(F) F
FROM
(
SELECT item, p_1year [Year],
CASE WHEN class = 'A' THEN c_yr_rate_1year ELSE 0 END 'A',
CASE WHEN class = 'F' THEN c_yr_rate_1year ELSE 0 END 'F'
FROM your_table
UNION ALL
SELECT item, p_2year [Year],
CASE WHEN class = 'A' THEN c_yr_rate_2year ELSE 0 END 'A',
CASE WHEN class = 'F' THEN c_yr_rate_2year ELSE 0 END 'F'
FROM your_table
UNION ALL
SELECT item, p_3year [Year],
CASE WHEN class = 'A' THEN c_yr_rate_3year ELSE 0 END 'A',
CASE WHEN class = 'F' THEN c_yr_rate_3year ELSE 0 END 'F'
FROM your_table
)A
GROUP BY item, [Year]
ORDER BY 2
只有在知道列“class”具有很少更改的静态值时,才可以使用pivot执行此操作,否则必须将此pivot构建为字符串,并使用“execute sp_executesql”执行
SELECT *
FROM
(
SELECT item, class, p_1year as year, c_yr_ret_1 as value FROM table_name
union all
SELECT item, class, p_2year, c_yr_ret_2 FROM table_name
union all
SELECT item, class, p_3year, c_yr_ret_3 FROM table_name
) table1
PIVOT
(
SUM(value) for class in ([A], [F])
) as pivoted_table;
只有在知道列“class”具有很少更改的静态值时,才可以使用pivot执行此操作,否则必须将此pivot构建为字符串,并使用“execute sp_executesql”执行
SELECT *
FROM
(
SELECT item, class, p_1year as year, c_yr_ret_1 as value FROM table_name
union all
SELECT item, class, p_2year, c_yr_ret_2 FROM table_name
union all
SELECT item, class, p_3year, c_yr_ret_3 FROM table_name
) table1
PIVOT
(
SUM(value) for class in ([A], [F])
) as pivoted_table;
到目前为止,我认为最简单的方法是使用
apply
和条件聚合:
select item, year,
max(case when class = 'A' then c end) as a,
max(case when class = 'F' then c end) as f
from tb1 cross apply
(values (p_1year, c_yr_ret1),
(p_2year, c_yr_ret2),
(p_3year, c_yr_ret3)
) v(year, c)
group by item, year
order by item, year desc;
apply
通常比使用union all
具有更好的性能,因为它只扫描基础表一次
是一个数据字典。到目前为止,我认为最简单的方法是使用
apply
和条件聚合:
select item, year,
max(case when class = 'A' then c end) as a,
max(case when class = 'F' then c end) as f
from tb1 cross apply
(values (p_1year, c_yr_ret1),
(p_2year, c_yr_ret2),
(p_3year, c_yr_ret3)
) v(year, c)
group by item, year
order by item, year desc;
apply
通常比使用union all
具有更好的性能,因为它只扫描基础表一次
是一个dbfiddle。使用示例数据创建一个简单脚本而不是图像使用示例数据创建一个简单脚本