我有一个客户表,其中有几种"帐户",每个都有不同的整数余额,例如
CUSTID AcctType Balance
12345 Checking 1000
12345 Savings 5000
12345 Investment 3000
98765 Savings 2000
98765 Checking 8000
98765 Investment 1000
98765 Retirement 2500
我不知道客户可能拥有多少帐户(可能是1到6之间的任何帐户)。我必须按照从最高到最低的顺序创建一个显示“帐户和余额”列的结果,如下所示:
CUSTID AcctType1 Balance1 AcctType2 Balance2 AcctType3 Balance3 AcctType4 Balance 4
12345 Savings 5000 Investment 3000 Checking 1000
98765 Checking 8000 Retirement 2500 Savings 2000 Investment 1000
如何在SQL Server中创建它? (理想情况下作为观点)
答案 0 :(得分:2)
您可以先将unpivot
列添加到行中,然后pivot
将行返回到包含行号的列中,如下所示:
WITH CTE
AS
(
SELECT
CAST(CUSTID AS NVARCHAR(50)) AS CUSTID
,CAST(AcctType AS NVARCHAR(50)) AS AcctType
,CAST(Balance AS NVARCHAR(50)) AS Balance
,ROW_NUMBER() OVER(PARTITION BY [CUSTID] ORDER BY Balance DESC) AS RN
FROM Data
), unpivoted
AS
(
SELECT CUSTID, val, col + ' ' + CAST(RN AS NVARCHAR(50)) AS col
FROM CTE
UNPIVOT
(
val
FOR col IN(AcctType, Balance)
) AS u
)
SELECT *
FROM unpivoted AS u
PIVOT
(
MAX(val)
FOR col IN([AcctType 1], [Balance 1],
[AcctType 2], [Balance 2],
[AcctType 3], [Balance 3],
[AcctType 4], [Balance 4])
) AS p;
<强>更新强>
如果您想为任意数量的客户提供动态,您必须动态执行此操作:
DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);
WITH CTE
AS
(
SELECT
CAST(CUSTID AS NVARCHAR(50)) AS CUSTID
,CAST(AcctType AS NVARCHAR(50)) AS AcctType
,CAST(Balance AS NVARCHAR(50)) AS Balance
,ROW_NUMBER() OVER(PARTITION BY [CUSTID] ORDER BY Balance DESC) AS RN
FROM Data
), Data
AS
(
SELECT col, MAX(RN) AS RN
FROM
(
SELECT RN, col + CAST(RN AS NVARCHAR(50)) AS col
FROM CTE
UNPIVOT
(
val
FOR col IN(AcctType, Balance)
) AS u
) AS t
GROUP BY col
)
select @cols = STUFF((SELECT ',' +
QUOTENAME(col)
FROM Data
ORDER BY RN
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT @query = 'WITH CTE
AS
(
SELECT
CAST(CUSTID AS NVARCHAR(50)) AS CUSTID
,CAST(AcctType AS NVARCHAR(50)) AS AcctType
,CAST(Balance AS NVARCHAR(50)) AS Balance
,ROW_NUMBER() OVER(PARTITION BY [CUSTID] ORDER BY Balance DESC) AS RN
FROM Data
), unpivoted
AS
(
SELECT CUSTID, val, col + CAST(RN AS NVARCHAR(50)) AS col
FROM CTE
UNPIVOT
(
val
FOR col IN(AcctType, Balance)
) AS u
)
SELECT *
FROM unpivoted AS u
PIVOT
(
MAX(val)
FOR col IN('+ @cols + ')
) AS p;';
EXECUTE(@query);
答案 1 :(得分:1)
如果列数有限(正如您所说的那样,每CUSTID
只有6个),那么您可以使用ROW_NUMBER()
条件聚合:
SELECT t.custID,
MAX(CASE WHEN t.rnk = 1 THEN t.accttype END) as accttype1,
MAX(CASE WHEN t.rnk = 1 THEN t.balance END) as balance1,
MAX(CASE WHEN t.rnk = 2 THEN t.accttype END) as accttype2,
MAX(CASE WHEN t.rnk = 2 THEN t.balance END) as balance2,
MAX(CASE WHEN t.rnk = 3 THEN t.accttype END) as accttype3,
MAX(CASE WHEN t.rnk = 3 THEN t.balance END) as balance3,
MAX(CASE WHEN t.rnk = 4 THEN t.accttype END) as accttype4,
MAX(CASE WHEN t.rnk = 4 THEN t.balance END) as balance4,
MAX(CASE WHEN t.rnk = 5 THEN t.accttype END) as accttype5,
MAX(CASE WHEN t.rnk = 5 THEN t.balance END) as balance5,
MAX(CASE WHEN t.rnk = 6 THEN t.accttype END) as accttype6,
MAX(CASE WHEN t.rnk = 6 THEN t.balance END) as balance6
FROM (SELECT s.*,
ROW_NUMBER() OVER(PARTITION BY s.custID ORDER BY s.balance DESC) as rnk
FROM YourTable s) t
GROUP BY t.custID