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.