我已经搜索了这个问题的答案并发现了类似于我自己的问题,但是我没有“ColumnHeader”列来表示记录应该进入哪个字段。例如:
TSQL Pivot without aggregate function
trying to flatten rows into columns
Fetching Columns of a multiple rows in one row
我的问题是 - 我有这种格式的数据(从产品推荐查询中选择为前三名):
------------------------------
CustID | StyleNo | Brand | ID
------------------------------
1 | ABC | BrandA| 1
------------------------------
1 | DEF | BrandB| 2
------------------------------
1 | GHI | BrandC| 3
------------------------------
2 | JKL | BrandA| 4
------------------------------
2 | MNO | BrandB| 5
------------------------------
2 | PQR | BrandD| 6
------------------------------
我想看起来像这样:
-----------------------------------------------------------------
CustID | StyleNo1| StyleNo2| StyleNo3 | Brand1 | Brand2 | Brand3
-----------------------------------------------------------------
1 | ABC | DEF | GHI | BrandA | BrandB | BrandC
-----------------------------------------------------------------
2 | JKL | MNO | PQR | BrandA | BrandB | BrandD
-----------------------------------------------------------------
为了让我的程序只为每位客户阅读一行建议。
我所尝试的是PIVOT
- 但是我没有什么可以真正地聚合在一起。我还尝试了第二个链接问题中概述的Min(Case...When...Then...End)
,但如上所述,我没有提到“标题”列。
ID列暂时无关紧要,但它可能有助于解决此问题。最终结果不需要它。
我目前正在使用SQLServer 2012
答案 0 :(得分:3)
使用窗口函数Row_Number()和条件聚合
Select CustID
,StyleNo1 = max(case when RN=1 then StyleNo else null end)
,StyleNo2 = max(case when RN=2 then StyleNo else null end)
,StyleNo3 = max(case when RN=3 then StyleNo else null end)
,Brand1 = max(case when RN=1 then Brand else null end)
,Brand2 = max(case when RN=2 then Brand else null end)
,Brand3 = max(case when RN=3 then Brand else null end)
From (
Select *,RN = Row_Number() over (Partition By CustID Order by StyleNo,Brand)
From YourTable
) A
Where RN<=3
Group By CustID
返回
答案 1 :(得分:1)
您正在做的事情被称为&#34;旋转&#34; - 为此你可以使用PIVOT。恕我直言的更好方法是使用Jeff Moden在this article中谈到的方法。
WITH idSort AS
(
SELECT *, rn = ROW_NUMBER() OVER (PARTITION BY CustID ORDER BY ID) FROM @yourTable
)
SELECT
CustID,
StyleNo1 = MAX(CASE rn WHEN 1 THEN StyleNo END),
StyleNo2 = MAX(CASE rn WHEN 2 THEN StyleNo END),
StyleNo3 = MAX(CASE rn WHEN 3 THEN StyleNo END),
Brand1 = MAX(CASE rn WHEN 1 THEN Brand END),
Brand2 = MAX(CASE rn WHEN 2 THEN Brand END),
Brand3 = MAX(CASE rn WHEN 3 THEN Brand END)
FROM idSort
GROUP BY CustID;
答案 2 :(得分:0)
其他方法可以使用CTE和Cross Apply。
CREATE TABLE #UnFlattenedData
(
CustID TINYINT ,
StyleNo CHAR(3) ,
Brand CHAR(6) ,
ID TINYINT
);
INSERT INTO #UnFlattenedData
( CustID, StyleNo, Brand, ID )
VALUES ( 1, -- CustID - tinyint
'ABC', -- StyleNo - char(3)
'BrandA', -- Brand - char(6)
1 -- ID - tinyint
),
( 1, -- CustID - tinyint
'DEF', -- StyleNo - char(3)
'BrandB', -- Brand - char(6)
2 -- ID - tinyint
),
( 1, -- CustID - tinyint
'GHI', -- StyleNo - char(3)
'BrandC', -- Brand - char(6)
3 -- ID - tinyint
),
( 2, -- CustID - tinyint
'JKL', -- StyleNo - char(3)
'BrandA', -- Brand - char(6)
4 -- ID - tinyint
),
( 2, -- CustID - tinyint
'MNO', -- StyleNo - char(3)
'BrandB', -- Brand - char(6)
5 -- ID - tinyint
),
( 2, -- CustID - tinyint
'PQR', -- StyleNo - char(3)
'BrandD', -- Brand - char(6)
6 -- ID - tinyint
);
WITH cte
AS ( SELECT * ,
ROW_NUMBER() OVER ( PARTITION BY u1.CustID ORDER BY u1.ID ) AS R1
FROM #UnFlattenedData AS u1
),
u1
AS ( SELECT C1.CustID ,
U1.StyleNo ,
U1.Brand
FROM cte AS C1
INNER JOIN #UnFlattenedData AS U1 ON U1.CustID = C1.CustID
AND U1.ID = C1.ID
WHERE C1.R1 = 1
),
u2
AS ( SELECT C1.CustID ,
U1.StyleNo ,
U1.Brand
FROM cte AS C1
INNER JOIN #UnFlattenedData AS U1 ON U1.CustID = C1.CustID
AND U1.ID = C1.ID
WHERE C1.R1 = 2
),
u3
AS ( SELECT C1.CustID ,
U1.StyleNo ,
U1.Brand
FROM cte AS C1
INNER JOIN #UnFlattenedData AS U1 ON U1.CustID = C1.CustID
AND U1.ID = C1.ID
WHERE C1.R1 = 3
)
SELECT u1.CustID ,
u1.StyleNo AS StyleNo1 ,
u2.StyleNo AS StyleNo2 ,
u3.StyleNo AS StyleNo3 ,
u1.Brand AS Brand1 ,
u2.Brand AS Brand2 ,
u3.Brand AS Brand3
FROM u1
CROSS APPLY ( SELECT *
FROM u2
WHERE u2.CustID = u1.CustID
) AS u2
CROSS APPLY ( SELECT *
FROM u3
WHERE u3.CustID = u1.CustID
) AS u3;