如何在不知道 T-SQL 中的固定列的情况下旋转

How to pivot without knowing fixed columns in T-SQL

我有一个名为 balance 的 table,我希望对其进行透视,但是这非常困难,因为列名称将标记为 1、2、3 并且余额将按降序排序每个客户。

这是当前 table 的屏幕截图:

和枢轴table:

我查看了其他视频和 post 但我没有找到符合我当前情况的解决方案,我想达到的目标。因此最终结果将是客户按升序排序,余额按降序排序。因此,对于客户 3,最高余额 500 将放在第 1 列,300 放在第 2 列,250 放在第 3 列。

创建示例数据的脚本:

select Customer, Balance
into #a
from (
values
  (1,     250), 
  (2,     500), 
  (1,     205), 
  (2,     600), 
  (2,     700),
  (3,     300),
  (3,     500),
  (3,     250)
) v (Customer, Balance)

Demo on db<>fiddle

您可以使用ROW_NUMBER()来标记值的个数,例如:1, 2, 3.

注意:ORDER BY [Balance] DESC来获取你想要的生成值

DECLARE 
    @columns NVARCHAR(MAX) = '',
    @sql     NVARCHAR(MAX) = '';


 SELECT Customer, Balance, Col = ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY [Balance] DESC)
 into #b
 FROM #a

SELECT @columns += QUOTENAME(Col) + ','
from (SELECT DISTINCT Col FROM #b) A

-- remove the last comma
SET @columns = LEFT(@columns, LEN(@columns) - 1);


SET @sql = 'SELECT * FROM ( SELECT Customer, Balance, Col FROM  #b) src PIVOT( MAX([Balance]) FOR Col IN ('+ @columns +')) AS pivot_table;';

-- execute the dynamic SQL
EXECUTE sp_executesql @sql;

输出

已更新

自连接字符串后 is undocumented and unreliable。它并不总是按预期工作。所以你应该用下面的 2 个解决方案来解决

  1. 使用 STRING_AGG(来自 SQL Server 2017 及以后版本)
SELECT STRING_AGG(QUOTENAME(Col), ', ')
from (SELECT DISTINCT Col FROM #b) A
// Output: [1], [2], [3]
  1. 使用XML Extensions
DECLARE  @columns NVARCHAR(MAX) = ''
SELECT @columns = (
  SELECT QUOTENAME(Col) + ', '
  FROM (SELECT DISTINCT Col FROM #b) A

  FOR XML PATH(''), TYPE
                   ).value('.','varchar(max)')
SELECT @columns 
// Output: [1], [2], [3],

感谢@GarethD 的评论。在 db<>fiddle

上查看

你可以这样试试

select *,concat('Price',RANK() OVER (PARTITION BY i.REFERENCE_NO ORDER BY i.TASK_ID 
 DESC)) AS Rank  into #temp from [dbo].[Table_1] i

 select REFERENCE_NO,Price1,Price2,Price3 from 
   (
    select REFERENCE_NO,TASK_ID,Rank from #temp
    ) as cte 
    PIVOT (SUM(TASK_ID)
    FOR rank IN (Price1,Price2,Price3 ))
    as PVT

试试这个。

declare @balanceAMTCols varchar(max)='',
@statement nvarchar(4000)=''

 select @balanceAMTCols= stuff( 
            (
                select ','+ QUOTENAME(balanceamtcol) from (
             select  distinct   convert(varchar(10),(row_number() over(partition by Customer order by Customer))) 
            balanceamtcol FROM #a   ) as tbl
            for xml path('')),1,1,'')

set @statement= 'select Customer,'+@balanceAMTCols+' from (
    select  Customer,Balance,convert(varchar(10),(row_number() over(partition by Customer order by Customer))) as balanceamtcol  FROM #a  
) [CustomerTbl]
pivot
(
    max(Balance)
    for balanceamtcol
    in ('+@balanceAMTCols+') ) as pivatetble'

exec sp_executesql  @statement