在 SQL Server 2008 中将行转换为列
Convert rows to columns in SQL Server 2008
我们有一个 table 叫做 Licenses。这是它的样子:
CustNum
LicenseAddress
License
ExpiryDate
155
123
Y32CA
12/31/2018
155
998
Y32CB
12/31/2020
155
568
Y32CC
12/31/2022
这是我想要的样子:
LicAddr1
Lic1
ExpiryDate1
LicAddr2
Lic2
ExpiryDate2
LicAddr3
Lic3
ExpiryDate3
123
Y32CA
12/31/2018
998
Y32CB
12/31/2020
568
Y32CC
12/31/2022
这是我目前的查询,但它只返回 NULL:
SELECT LicAddr1,
Lic1,
ExpiryDate1,
LicAddr2,
Lic2,
ExpiryDate2,
LicAddr3,
Lic3,
ExpiryDate3
FROM (SELECT CustNum, LicenseAddress, License, ExpiryDate FROM Licenses) d
PIVOT (
MAX(ExpiryDate)
FOR CustNum IN (LicAddr1, Lic1, ExpiryDate1, LicAddr2, Lic2, ExpiryDate2, LicAddr3, Lic3, ExpiryDate3)
) piv
我做错了什么?
PIVOT
并不是你真正想要的,特别是因为你试图从每一行中获取多个值(这对聚合 PIVOT
尝试不太有效提供)。
我在这里假设您想要最新的三个许可证,在这种情况下,我们可以为每个 CustNum
应用一个行号,按 ExpiryDate
排序(最新的在前),然后翻转它们他们是 left-to-right oldest-to-newest:
;WITH cte AS
(
SELECT CustNum, LicenseAddress, License, ExpiryDate,
rn = ROW_NUMBER() OVER (PARTITION BY CustNum ORDER BY ExpiryDate DESC)
FROM dbo.Licenses
)
SELECT CustNum,
LicAddr1 = MAX(CASE WHEN rn = 3 THEN LicenseAddress END),
Lic1 = MAX(CASE WHEN rn = 3 THEN License END),
ExpiryDate1 = MAX(CASE WHEN rn = 3 THEN ExpiryDate END),
LicAddr2 = MAX(CASE WHEN rn = 2 THEN LicenseAddress END),
Lic2 = MAX(CASE WHEN rn = 2 THEN License END),
ExpiryDate2 = MAX(CASE WHEN rn = 2 THEN ExpiryDate END),
LicAddr3 = MAX(CASE WHEN rn = 1 THEN LicenseAddress END),
Lic3 = MAX(CASE WHEN rn = 1 THEN License END),
ExpiryDate3 = MAX(CASE WHEN rn = 1 THEN ExpiryDate END)
FROM cte
GROUP BY CustNum;
结果:
CustNum
LicAddr1
Lic1
ExpiryDate1
LicAddr2
Lic2
ExpiryDate2
LicAddr3
Lic3
ExpiryDate3
155
123
Y32CA
2018-12-31
998
Y32CB
2020-12-31
568
Y32CC
2022-12-31
我们有一个 table 叫做 Licenses。这是它的样子:
CustNum | LicenseAddress | License | ExpiryDate |
---|---|---|---|
155 | 123 | Y32CA | 12/31/2018 |
155 | 998 | Y32CB | 12/31/2020 |
155 | 568 | Y32CC | 12/31/2022 |
这是我想要的样子:
LicAddr1 | Lic1 | ExpiryDate1 | LicAddr2 | Lic2 | ExpiryDate2 | LicAddr3 | Lic3 | ExpiryDate3 |
---|---|---|---|---|---|---|---|---|
123 | Y32CA | 12/31/2018 | 998 | Y32CB | 12/31/2020 | 568 | Y32CC | 12/31/2022 |
这是我目前的查询,但它只返回 NULL:
SELECT LicAddr1,
Lic1,
ExpiryDate1,
LicAddr2,
Lic2,
ExpiryDate2,
LicAddr3,
Lic3,
ExpiryDate3
FROM (SELECT CustNum, LicenseAddress, License, ExpiryDate FROM Licenses) d
PIVOT (
MAX(ExpiryDate)
FOR CustNum IN (LicAddr1, Lic1, ExpiryDate1, LicAddr2, Lic2, ExpiryDate2, LicAddr3, Lic3, ExpiryDate3)
) piv
我做错了什么?
PIVOT
并不是你真正想要的,特别是因为你试图从每一行中获取多个值(这对聚合 PIVOT
尝试不太有效提供)。
我在这里假设您想要最新的三个许可证,在这种情况下,我们可以为每个 CustNum
应用一个行号,按 ExpiryDate
排序(最新的在前),然后翻转它们他们是 left-to-right oldest-to-newest:
;WITH cte AS
(
SELECT CustNum, LicenseAddress, License, ExpiryDate,
rn = ROW_NUMBER() OVER (PARTITION BY CustNum ORDER BY ExpiryDate DESC)
FROM dbo.Licenses
)
SELECT CustNum,
LicAddr1 = MAX(CASE WHEN rn = 3 THEN LicenseAddress END),
Lic1 = MAX(CASE WHEN rn = 3 THEN License END),
ExpiryDate1 = MAX(CASE WHEN rn = 3 THEN ExpiryDate END),
LicAddr2 = MAX(CASE WHEN rn = 2 THEN LicenseAddress END),
Lic2 = MAX(CASE WHEN rn = 2 THEN License END),
ExpiryDate2 = MAX(CASE WHEN rn = 2 THEN ExpiryDate END),
LicAddr3 = MAX(CASE WHEN rn = 1 THEN LicenseAddress END),
Lic3 = MAX(CASE WHEN rn = 1 THEN License END),
ExpiryDate3 = MAX(CASE WHEN rn = 1 THEN ExpiryDate END)
FROM cte
GROUP BY CustNum;
结果:
CustNum | LicAddr1 | Lic1 | ExpiryDate1 | LicAddr2 | Lic2 | ExpiryDate2 | LicAddr3 | Lic3 | ExpiryDate3 |
---|---|---|---|---|---|---|---|---|---|
155 | 123 | Y32CA | 2018-12-31 | 998 | Y32CB | 2020-12-31 | 568 | Y32CC | 2022-12-31 |