SQL 服务器以及如何将行转换为列
SQL Server and how to convert rows to columns
我想使用 SQL 服务器将列转换为行。 unpivot我已经试过了,但是我没有足够的知识来制作它,只能制作一列。
这是原来的脚本 table:
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
最后的 table 应该是这样的:
谢谢!
一种方法是,
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,具体取决于您以后是否决定在同一字段上使用聚合函数。零将使求和更容易。 Null 将使平均值更容易。
试试这个-
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' 具有很少更改的静态值时,您才能使用数据透视来完成此操作,否则您必须将此数据透视构建为字符串并使用 '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
具有更好的性能,因为它只扫描底层 table 一次。
Here 是一个 db<>fiddle.
我想使用 SQL 服务器将列转换为行。 unpivot我已经试过了,但是我没有足够的知识来制作它,只能制作一列。
这是原来的脚本 table:
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
最后的 table 应该是这样的:
谢谢!
一种方法是,
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,具体取决于您以后是否决定在同一字段上使用聚合函数。零将使求和更容易。 Null 将使平均值更容易。
试试这个-
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' 具有很少更改的静态值时,您才能使用数据透视来完成此操作,否则您必须将此数据透视构建为字符串并使用 '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
具有更好的性能,因为它只扫描底层 table 一次。
Here 是一个 db<>fiddle.