【问题标题】:Concatenate dynamically pivoted columns for a variable number of columns为可变数量的列连接动态旋转的列
【发布时间】:2019-07-07 23:26:15
【问题描述】:

我已经能够成功地将不同的字段值转换为单独的列,但我想要将所有这些单独的(转换的)列连接到一列中。我不知道在运行时最终会得到多少转轴列,所以我不能只使用 Column1 + Column2 + Column3 等。

这是我的 sql

--Create a table variable to hold my source data

declare @datatable  table
(
    OrderId             int,
    ProductId           int,
    ClientName          varchar(50)
)

--insert some data
insert into         @datatable values (1, 2, 'Joe Bloggs')
insert into         @datatable values (1, 2, 'Frank Bloggs')

--Create a temp table

--that introduces a new field (called Header)
--to give me column names for my pivoted data

IF OBJECT_ID('tempdb..#PivotedClients') IS NOT NULL DROP TABLE #PivotedClients

create table        #PivotedClients
            (
               OrderId  int,
               ProductId    int,
               ClientName   varchar(50),
               Header   varchar(100)
            )

insert into     #PivotedClients
  select            OrderId,
            ProductId,
            ClientName,
            'Client ' + Cast(Rank() Over (Partition by OrderId                   
  order by ClientName) as varchar(3)) 
  from          @datatable

--Create variables to hold my column names
--and my (dynamic) sql

declare @pivotcolumns       nvarchar(max),
    @colsWithNoNulls    nvarchar(max),
    @sqlquery       nvarchar(max)

set @pivotcolumns = STUFF(
                (
                  select distinct ',' + QUOTENAME(Header)
                  from #PivotedClients
                  for XML PATH (''), TYPE
                        ).value('.', 'nvarchar(max)')
                ,1,1,'')

set @colsWithNoNulls = STUFF(
                  (
                               SELECT DISTINCT ',ISNULL(' + QUOTENAME(Header) + ', '''') ' + QUOTENAME(Header)
                                        FROM #PivotedClients
         for XML PATH (''), TYPE
    ).value('.', 'NVARCHAR(max)')
    ,1,1,''
        )

if OBJECT_ID('tempdb..##Clients ') is not null drop TABLE ##Clients

set @sqlquery = 'select distinct OrderId,
                         ProductID,
                    ' + @colsWithNoNulls + ' 
            into        ##Clients
            from
                (
                   select   OrderId,
                                        ClientName,
                            ProductID,
                        Header
                       from #PivotedClients) x
                pivot 
                (
                   Max(ClientName)
                   for Header in (' + @pivotcolumns + ')
                )   p' 

exec sp_executesql @sqlquery

----
select *
from ##Clients
----

我目前最终得到的记录集是:

OrderId ProductId  Client1       Client 2
1       2          Frank Bloggs  Joe Blogs

我想要的是:

OrderID ProductId Clients
1       2         Frank Bloggs Joe Bloggs

我不知道在运行时最终会得到多少“透视”列,所以我不能只使用 Client1 + Client2 等

【问题讨论】:

  • 您使用的是什么版本的 SQL Server?如果您只使用 string_agg() (或未实现 string_agg 的版本中的 xml 路径的东西),您可能根本不需要旋转。例如,摆脱所有 pivotedclients 的东西,只做一个简单的select orderid, productid, clients = string_agg(clientname, ' ') from @datatable group by orderid, productid;
  • 谢谢戴尔。那真是太棒了。第一次工作。非常感谢您的帮助。
  • @mmmg 我想你是想感谢 ZLK - 我没有提供任何解决方案。
  • 感谢 ZLK 和 Dale 让我知道。

标签: sql-server pivot string-concatenation


【解决方案1】:

只需更改您的@colsWithNoNulls 即可执行字符串连接

set @colsWithNoNulls = STUFF(
                (
                    SELECT  DISTINCT '+ '' '' +  ISNULL(' + QUOTENAME(Header) + ', '''')' 
                                        FROM    #PivotedClients
                    for XML PATH (''), TYPE
                ).value('.', 'NVARCHAR(max)')
                , 1, 1, '') + 'AS Clients'

您也可以在sp_executesql 之前执行print @sqlquery。这将帮助您调试动态查询

【讨论】:

  • 嗨松鼠,谢谢。您的解决方案也有效。我将使用 STRING_AGG 运行 Dale 的解决方案,因为它消除了对复杂旋转的需要。我会将您的建议存档,以防万一我使用的 SQL Server 版本没有 string_agg。关于打印 sql 的好建议,因为它可以让您看到发送到 sql server 引擎的确切 sql。
  • STRING_AGG 只能从SQL Server 2017 开始使用
猜你喜欢
  • 2013-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-01
  • 1970-01-01
  • 2012-11-22
  • 1970-01-01
  • 2020-03-11
相关资源
最近更新 更多