我有一张名为Car的表:
CREATE TABLE [dbo].[Car](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Brand] [nchar](10) NOT NULL
)
和一个叫Passenger:
CREATE TABLE [dbo].[Passenger](
[ID] [int] IDENTITY(1,1) NOT NULL,
[CarID] [int] NOT NULL,
[Name] [nchar](10) NOT NULL
)
包含以下数据:
+----+------------+
| ID | Brand |
+----+------------+
| 1 | Ford |
| 2 | Audi |
+----+------------+
+----+-------+------------+
| ID | CarID | Name |
+----+-------+------------+
| 1 | 1 | Joe |
| 2 | 1 | Jack |
| 3 | 1 | Jim |
| 4 | 2 | Bob |
| 5 | 2 | Frank |
+----+-------+------------+
另外,我对车内乘客数量的限制= 5.(业务逻辑)
我想要做的是在View表中显示这些数据,如下例所示:
+----+------------+------------+------------+------------+------------+------------+
| ID | Brand | Passenger1 | Passenger2 | Passenger3 | Passenger4 | Passenger5 |
+----+------------+------------+------------+------------+------------+------------+
| 1 | Ford | Joe | Jack | Jim | NULL | NULL |
| 2 | Audi | Bob | Frank | NULL | NULL | NULL |
+----+------------+------------+------------+------------+------------+------------+
因此,如果乘客少于5人,其余列为NULL,我们不需要处理超过5名乘客。
不需要对乘客进行订购,但NULLs
必须在最后(例如Frank, Bob, NULL, NULL, NULL is OK for Car ID 2, but Frank, NULL, NULL, Bob, NULL
不是。)如果也可以订购乘客,那么我更愿意订购他们的身份证。
如何使用 SQL Server 2012 进行数据转换?
答案 0 :(得分:3)
使用Pivot
运算符来转动数据
使用Row_number
窗口功能生成乘客编号,这样没有所有5名乘客的车最终都会有NULL
个值
;WITH cte
AS (SELECT c.id,
c.Brand,
'Passenger'+ Cast(Row_number() OVER(partition BY c.id ORDER BY p.id) AS VARCHAR(50)) p_name,
NAME
FROM [Car] c
JOIN [Passenger] p
ON c.ID = p.CarID)
SELECT *
FROM cte
PIVOT (Max(NAME)
FOR p_name IN(Passenger1,
Passenger2,
Passenger3,
Passenger4,
Passenger5 ))pv
ORDER BY id
Conditional Aggregate
方法
;WITH cte
AS (SELECT c.id,
c.Brand,
'Passenger'+ Cast(Row_number() OVER(partition BY c.id ORDER BY p.id) AS VARCHAR(50)) p_name,
NAME
FROM [Car] c
JOIN Passenger p
ON c.ID = p.CarID)
SELECT id,
Brand,
[Passenger1]=Max(CASE WHEN p_name = 'Passenger1' THEN NAME END),
[Passenger2]=Max(CASE WHEN p_name = 'Passenger2' THEN NAME END),
[Passenger3]=Max(CASE WHEN p_name = 'Passenger3' THEN NAME END),
[Passenger4]=Max(CASE WHEN p_name = 'Passenger4' THEN NAME END),
[Passenger5]=Max(CASE WHEN p_name = 'Passenger5' THEN NAME END)
FROM cte
GROUP BY id,
Brand
ORDER BY id
<强>结果:强>
╔════╦════════════╦════════════╦════════════╦════════════╦════════════╦════════════╗
║ id ║ Brand ║ Passenger1 ║ Passenger2 ║ Passenger3 ║ Passenger4 ║ Passenger5 ║
╠════╬════════════╬════════════╬════════════╬════════════╬════════════╬════════════╣
║ 1 ║ Ford ║ Joe ║ Jack ║ Jim ║ NULL ║ NULL ║
║ 2 ║ Audi ║ Bob ║ Frank ║ NULL ║ NULL ║ NULL ║
╚════╩════════════╩════════════╩════════════╩════════════╩════════════╩════════════╝
答案 1 :(得分:0)
UNTESTED:
我们在分区上使用row_num()按卡ID来获得5个位置的常数座位号添加P,因为我不确定SQL服务器是否可以有一个带有数字的列星,然后基于它来转动数据这5个派生值。
Select brand, P1, P2, P3, P4, P5
FROM
(
SELECT brand, name, 'P' & row_Number() Over (partition by CarID order by P.name) as PNum
FROM car C
INNER JOIN passenger P
on C.CardID = P.CardID
) src
PIVOT
(
max(src.name)
FOr pnum in ([P1],[P2],[P3],[P4],[P5])
) as PT