我正在使用SQL Server。我创建了一个查询:
SELECT
p.[accountNumber],
pf.fundid
FROM
[dbo].[Property] p
LEFT JOIN
dbo.propertyfundassessment pf ON p.id = pf.propertyid
LEFT JOIN
dbo.fund f ON pf.fundid = f.id
WHERE
p.accountnumber = '238492348' AND p.taxyear = 2018
这会将数据显示为:
accountNumber fundid
--------------------------
1 238492348 1004
2 238492348 1005
3 238492348 1006
4 238492348 1007
5 238492348 1008
6 238492348 1009
7 238492348 1022
8 238492348 1339
我正在尝试一些如何旋转表格以使表格看起来像这样:
accountNumber adv1 adv2 adv3 adv4 adv5 adv6 adv7 adv8
-----------------------------------------------------------------
1 238492348 1004 1005 1006 1007 1008 1009 1022 1339
有人可以协助我使用SQL Server做到这一点吗?
我发现了这个:
SELECT *
FROM
(SELECT ColNbr = ROW_NUMBER() OVER(PARTITION BY accountNUmber ORDER BY fundid,accountNumber)
,accountNumber
,fundid
FROM
#tmpS a
) src PIVOT(MAX(src.fundid) FOR src.ColNbr IN( [1]
,[2]
,[3]
,[4]
,[5]
,[6]
,[7]
,[8]
,[9]
,[10]
,[11]
,[12]
,[13]
,[14]
,[15]
,[16]
,[17]
,[18]
,[19]
,[20]
,[21]
,[22]
,[23]
,[24]
,[25]
)) pvt
我正在尝试将两个查询结合起来以使其动态执行。而不是尝试创建#tmpS
表。
任何帮助将不胜感激!
答案 0 :(得分:4)
您可以像下面这样组合两个查询:
;WITH StartingData AS
(
SELECT
[accountNumber] = p.[accountNumber],
fundid = pf.fundid,
FundRanking = ROW_NUMBER() OVER (PARTITION BY p.[accountNumber] ORDER BY pf.fundid ASC) -- The order by is crucial for the pivot ordering later
FROM
[dbo].[Property] p
left join dbo.propertyfundassessment pf on p.id = pf.propertyid
left join dbo.fund f on pf.fundid = f.id
where
p.taxyear = 2018
)
SELECT
P.accountNumber,
P.[1],
P.[2],
P.[3],
P.[4],
P.[5],
P.[6],
P.[7],
P.[8],
P.[9],
P.[10],
P.[11],
P.[12],
P.[13],
P.[14],
P.[15],
P.[16],
P.[17],
P.[18],
P.[19],
P.[20],
P.[21],
P.[22],
P.[23],
P.[24],
P.[25]
FROM
StartingData AS S
PIVOT (
MAX(S.fundid) FOR S.FundRanking IN (
[1], [2], [3], [4], [5], [6], [7], [8], [9], [10],
[11], [12], [13], [14], [15], [16], [17], [18],
[19], [20], [21], [22], [23], [24], [25])
) AS P
请紧记Tim所说的话,或者您将要旋转的fundid
的数量硬编码(此示例的硬编码从1到25),或者您必须使用动态SQL生成一个可以动态地调整到特定fundid
可能需要的最大accountNumber
数量的pivot语句。这将为每个初始记录按accountNumber
生成一列。
要使其动态,请使用以下命令:
IF OBJECT_ID('tempdb..#AccountFunds') IS NOT NULL
DROP TABLE #AccountFunds
SELECT
[accountNumber] = p.[accountNumber],
fundid = pf.fundid,
FundRanking = ROW_NUMBER() OVER (PARTITION BY p.[accountNumber] ORDER BY pf.fundid ASC) -- The order by is crucial for the pivot ordering later
INTO
#AccountFunds
FROM
[dbo].[Property] p
left join dbo.propertyfundassessment pf on p.id = pf.propertyid
left join dbo.fund f on pf.fundid = f.id
where
p.taxyear = 2018
AND p.[accountNumber] = '238492348'
DECLARE @PivotValues VARCHAR(MAX) = STUFF (
(
SELECT DISTINCT
',' + QUOTENAME(CONVERT(VARCHAR(10), A.FundRanking))
FROM
#AccountFunds AS A
ORDER BY
',' + QUOTENAME(CONVERT(VARCHAR(10), A.FundRanking)) ASC
FOR XML
PATH ('')
),
1, 1, '')
DECLARE @SelectColumnAlias VARCHAR(MAX) = STUFF (
(
SELECT
',P.' + QUOTENAME(CONVERT(VARCHAR(10), A.FundRanking)) + ' AS adv' + CONVERT(VARCHAR(10), A.FundRanking)
FROM
#AccountFunds AS A
GROUP BY
A.FundRanking
ORDER BY
A.FundRanking ASC
FOR XML
PATH ('')
),
1, 1, '')
DECLARE @DynamicSQL VARCHAR(MAX) = '
SELECT
P.AccountNumber,
' + @SelectColumnAlias + '
FROM
#AccountFunds AS A
PIVOT (
MAX(A.fundid) FOR A.FundRanking IN (
' + @PivotValues + ')
) AS P '
--PRINT (@DynamicSQL) -- Use Print to check the query
EXEC (@DynamicSQL)
如果您检查@PivotValues
的值,则类似于以下内容:
[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25]
@SelectColumnAlias
的值为:
P.[1] AS adv1,P.[2] AS adv2,P.[3] AS adv3,P.[4] AS adv4,P.[5] AS adv5,P.[6] AS adv6,P.[7] AS adv7,P.[8] AS adv8,P.[9] AS adv9,P.[10] AS adv10,P.[11] AS adv11,P.[12] AS adv12,P.[13] AS adv13,P.[14] AS adv14,P.[15] AS adv15,P.[16] AS adv16,P.[17] AS adv17,P.[18] AS adv18,P.[19] AS adv19,P.[20] AS adv20,P.[21] AS adv21,P.[22] AS adv22,P.[23] AS adv23,P.[24] AS adv24,P.[25] AS adv25
最后是完整表达:
SELECT
P.AccountNumber,
P.[1] AS adv1,P.[2] AS adv2,P.[3] AS adv3,P.[4] AS adv4,P.[5] AS adv5,P.[6] AS adv6,P.[7] AS adv7,P.[8] AS adv8,P.[9] AS adv9,P.[10] AS adv10,P.[11] AS adv11,P.[12] AS adv12,P.[13] AS adv13,P.[14] AS adv14,P.[15] AS adv15,P.[16] AS adv16,P.[17] AS adv17,P.[18] AS adv18,P.[19] AS adv19,P.[20] AS adv20,P.[21] AS adv21,P.[22] AS adv22,P.[23] AS adv23,P.[24] AS adv24,P.[25] AS adv25
FROM
#AccountFunds AS A
PIVOT (
MAX(A.fundid) FOR A.FundRanking IN (
[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25])
) AS P
答案 1 :(得分:2)
尝试使用此动态sql
IF OBJECT_ID('Tempdb..#temp')IS NOT NULL
DROP TABLE #temp
;WITH CTE(Id,accountNumber,fundid)
AS
(
SELECT 1,238492348,1004 UNION ALL
SELECT 2,238492348,1005 UNION ALL
SELECT 3,238492348,1006 UNION ALL
SELECT 4,238492348,1007 UNION ALL
SELECT 5,238492348,1008 UNION ALL
SELECT 6,238492348,1009 UNION ALL
SELECT 7,238492348,1022 UNION ALL
SELECT 8,238492348,1339
)
SELECT * ,'adv'+CAST(ROW_NUMBER()OVER(ORDER BY (SELECT 1)) AS VARCHAR(10)) AS tcol INTO #temp FROM CTE
DECLARE @Columns nvarchar(max),@IsnullColumns nvarchar(max)
,@Sql nvarchar(max)
SELECT @Columns= STUFF((SELECT ', '+tcol FROM #temp FOR XML PATH ('')),1,1,'')
SELECT @IsnullColumns=STUFF((SELECT ', '+'MAX('+QUOTENAME(tcol)+') AS ' +QUOTENAME(tcol) FROM #temp FOR XML PATH ('')),1,1,'')
SET @Sql='
SELECT accountNumber ,'+@IsnullColumns+'
FROM
(SELECT * FROM #temp
) AS SRC
PIVOT
(MAX(fundid) FOR tcol IN ('+@Columns+')
) AS PVT
GROUP BY accountNumber'
PRINT @Sql
EXEC (@Sql)
结果
accountNumber adv1 adv2 adv3 adv4 adv5 adv6 adv7 adv8
-----------------------------------------------------------------
238492348 1004 1005 1006 1007 1008 1009 1022 1339