将行转换为考虑多列的列

发布于 2025-01-31 23:01:02 字数 1998 浏览 3 评论 0原文

我有当前的基础表:

”在此处输入图像描述”

我需要将其转换为:

< img src =“ https://i.sstatic.net/0caad.png” alt =“在此处输入图像说明”>

我已经有一个动态SQL,在LTD值下面为我提供了下面的结果:

但我无法基于列有限公司和男孩动态创建聚合名称的列,并将邮政修复设置为列名称。

在下面找到我的SQL:

create table #tempIE
(
    AGGREGATIONNAME varchar(2),
    LTD decimal,
       BOY decimal,
       MONTH int
)

insert into #tempIE values ('XX', 50, 45, 00)
insert into #tempIE values ('XX', 150, 145, 01)
insert into #tempIE values ('XX', 300, 295, 02)

insert into #tempIE values ('YY', 25, 20, 00)
insert into #tempIE values ('YY', 50, 45, 01)
insert into #tempIE values ('YY', 75, 70, 02)

insert into #tempIE values ('ZZ', 500, 495, 00)
insert into #tempIE values ('ZZ', 600, 595, 01)
insert into #tempIE values ('ZZ', 700, 695, 02)

SELECT *
FROM #tempIE



DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.AGGREGATIONNAME) 
            FROM #tempIE c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT MONTH, ' + @cols + ' INTO ##tempIEnew from 
            (
                select AGGREGATIONNAME
                    , LTD
                                 --, BOY
                    , MONTH
                from #tempIE
           ) x
            pivot 
            (
                 max(LTD)
                for AGGREGATIONNAME in (' + @cols + ')
            ) p '
                    ;

execute(@query)



SELECT *
FROM ##tempIEnew

drop table #tempIE
drop table ##tempIEnew

I have current base table:

enter image description here

and I need to convert it to this:

enter image description here

I already have a dynamic SQL in place which is giving me below result for the LTD values:

enter image description here

But I am not able to create dynamically the columns for the Aggregationname based on the columns LTD and BOY and set the post fix to the column name.

Find my SQL below:

create table #tempIE
(
    AGGREGATIONNAME varchar(2),
    LTD decimal,
       BOY decimal,
       MONTH int
)

insert into #tempIE values ('XX', 50, 45, 00)
insert into #tempIE values ('XX', 150, 145, 01)
insert into #tempIE values ('XX', 300, 295, 02)

insert into #tempIE values ('YY', 25, 20, 00)
insert into #tempIE values ('YY', 50, 45, 01)
insert into #tempIE values ('YY', 75, 70, 02)

insert into #tempIE values ('ZZ', 500, 495, 00)
insert into #tempIE values ('ZZ', 600, 595, 01)
insert into #tempIE values ('ZZ', 700, 695, 02)

SELECT *
FROM #tempIE



DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.AGGREGATIONNAME) 
            FROM #tempIE c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT MONTH, ' + @cols + ' INTO ##tempIEnew from 
            (
                select AGGREGATIONNAME
                    , LTD
                                 --, BOY
                    , MONTH
                from #tempIE
           ) x
            pivot 
            (
                 max(LTD)
                for AGGREGATIONNAME in (' + @cols + ')
            ) p '
                    ;

execute(@query)



SELECT *
FROM ##tempIEnew

drop table #tempIE
drop table ##tempIEnew

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

顾忌 2025-02-07 23:01:02

正如我在评论中提到的那样,我更喜欢使用条件汇总而不是pivot运算符,因此可以更容易使用,因为它没有限制性的语法。

通过有条件的聚合,您可以轻松地实现以下静态枢轴:

SELECT IE.[MONTH],
       MAX(CASE IE.AGGREGATIONNAME WHEN 'XX' THEN IE.LTD END) AS XX_LTD,
       MAX(CASE IE.AGGREGATIONNAME WHEN 'YY' THEN IE.LTD END) AS YY_LTD,
       /* ... */
       MAX(CASE IE.AGGREGATIONNAME WHEN 'ZZ' THEN IE.BOY END) AS ZZ_BPY
FROM #tempIE IE
GROUP BY IE.[MONTH];

对于动态枢轴,然后可以通过以下内容实现此目标。

DECLARE @SQL nvarchar(MAX),
        @CRLF nchar(2) = NCHAR(13) + NCHAR(10);

DECLARE @Delim nvarchar(3) = N',' + @CRLF

SELECT @SQL = N'SELECT IE.[MONTH],' + @CRLF +
              STRING_AGG(N'       MAX(CASE IE.AGGREGATIONNAME WHEN ' + QUOTENAME(IE.AGGREGATIONNAME,'''') + N' THEN IE.LTD END) AS ' + QUOTENAME(CONCAT(IE.AGGREGATIONNAME,'_LTD')),@Delim) WITHIN GROUP (ORDER BY IE.AGGREGATIONNAME) + N',' + @CRLF +
              STRING_AGG(N'       MAX(CASE IE.AGGREGATIONNAME WHEN ' + QUOTENAME(IE.AGGREGATIONNAME,'''') + N' THEN IE.BOY END) AS ' + QUOTENAME(CONCAT(IE.AGGREGATIONNAME,'_BOY')),@Delim) WITHIN GROUP (ORDER BY IE.AGGREGATIONNAME) + @CRLF +
              N'FROM #tempIE IE' + @CRLF +
              N'GROUP BY IE.[MONTH];'
FROM (SELECT DISTINCT AGGREGATIONNAME
      FROM #tempIE) IE;

--PRINT @SQL;--Your best friend

EXEC sys.sp_executesql @SQL;

请注意,我假设您使用的是SQL Server的完全支持版本(虽然没有注意到您不是),因此无需为XML Path 和2个通过。我还切换到创建查询内联,因为尝试使用变量@columns尝试使用该查询,这是一个真正的痛苦,有条件聚合。实际上,我不建议该方法各自导致(例如Pivot)。

As I mentioned in the comments, I much more prefer using conditional aggregation rather than the PIVOT operator, it's so much easier to work with as it's not got restrictive syntax.

With conditional aggregation, you can easily achieve a static pivot with the following:

SELECT IE.[MONTH],
       MAX(CASE IE.AGGREGATIONNAME WHEN 'XX' THEN IE.LTD END) AS XX_LTD,
       MAX(CASE IE.AGGREGATIONNAME WHEN 'YY' THEN IE.LTD END) AS YY_LTD,
       /* ... */
       MAX(CASE IE.AGGREGATIONNAME WHEN 'ZZ' THEN IE.BOY END) AS ZZ_BPY
FROM #tempIE IE
GROUP BY IE.[MONTH];

For a dynamic pivot, then you could achieve this with the following.

DECLARE @SQL nvarchar(MAX),
        @CRLF nchar(2) = NCHAR(13) + NCHAR(10);

DECLARE @Delim nvarchar(3) = N',' + @CRLF

SELECT @SQL = N'SELECT IE.[MONTH],' + @CRLF +
              STRING_AGG(N'       MAX(CASE IE.AGGREGATIONNAME WHEN ' + QUOTENAME(IE.AGGREGATIONNAME,'''') + N' THEN IE.LTD END) AS ' + QUOTENAME(CONCAT(IE.AGGREGATIONNAME,'_LTD')),@Delim) WITHIN GROUP (ORDER BY IE.AGGREGATIONNAME) + N',' + @CRLF +
              STRING_AGG(N'       MAX(CASE IE.AGGREGATIONNAME WHEN ' + QUOTENAME(IE.AGGREGATIONNAME,'''') + N' THEN IE.BOY END) AS ' + QUOTENAME(CONCAT(IE.AGGREGATIONNAME,'_BOY')),@Delim) WITHIN GROUP (ORDER BY IE.AGGREGATIONNAME) + @CRLF +
              N'FROM #tempIE IE' + @CRLF +
              N'GROUP BY IE.[MONTH];'
FROM (SELECT DISTINCT AGGREGATIONNAME
      FROM #tempIE) IE;

--PRINT @SQL;--Your best friend

EXEC sys.sp_executesql @SQL;

Note I assume you are using a fully supported version of SQL Server (as it's not noted you aren't) and so there's no need to FOR XML PATH and 2 passes of the table. I also switch to creating the query inline, as attempting to that with a variable @Columns is a real pain with conditional aggregation; I actually don't recommend that method either cause it's respective (like PIVOT).

db<>fiddle

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文