我是SQL Pivot的新手,所以我想详细解释一下。我的表格如下:
PID | NAME | PlateNumber | COUNTRY|
------------------------------------------
111 | Alex | ab123456 | GB |
------------------------------------------
111 | Alex | fe123344 | ES |
------------------------------------------
111 | Alex | r223456e | US |
------------------------------------------
112 | Simon | t22er563 | GB |
------------------------------------------
112 | Simon | q32345ke | DE |
------------------------------------------
113 | Ben | ve923456 | IT |
------------------------------------------
我希望得到以下格式的结果:
PID |NAME |PlateNumber1|PlateNumber2| PlateNumber3|COUNTRY1| COUNTRY2| COUNTRY3|
--------------------------------------------------------------------------------
111 | Alex | ab123456 | fe123344 | r223456e | GB | ES | US |
--------------------------------------------------------------------------------
112 | Simon | t22er563| q32345ke | | GB | DE | |
--------------------------------------------------------------------------------
113 | Ben | ve923456| | | IT | | |
--------------------------------------------------------------------------------
你能帮帮我吗?
提前谢谢!
答案 0 :(得分:1)
使用PIVOT
:
with your_table(PID , NAME , PlateNumber , Country) as (
select 111 , 'Alex' , 'ab123456' , 'GB' union all
select 111 , 'Alex' , 'fe123344' , 'ES' union all
select 111 , 'Alex' , 'r223456e' , 'US' union all
select 112 , 'Simon' , 't22er563' , 'GB' union all
select 112 , 'Simon' , 'q32345ke' , 'DE' union all
select 113 , 'Ben' , 've923456' , 'IT'
)
select pid,
name,
max(PlateNumber1) PlateNumber1,
max(PlateNumber2) PlateNumber2,
max(PlateNumber3) PlateNumber3,
max(Country1) Country1,
max(Country2) Country2,
max(Country3) Country3
from (
select *,
'Country' + cast(row_number() over (
partition by PID order by pnum
) as varchar(30)) cn
from (
select t.*,PlateNumber pnum,
'PlateNumber' + cast(row_number() over (
partition by PID order by PlateNumber
) as varchar(30)) pn
from your_table t
) t
pivot(max(PlateNumber) for pn in ([PlateNumber1], [PlateNumber2], [PlateNumber3])) x
) t
pivot(max(Country) for cn in ([Country1], [Country2], [Country3])) x
group by pid,
name;
答案 1 :(得分:1)
传统的交叉表/条件聚合版本就是这样:
测试设置:http://rextester.com/SKMUL25726
select
pid
, name
, PlateNumber1 = max(case when rn = 1 then PlateNumber end)
, PlateNumber2 = max(case when rn = 2 then PlateNumber end)
, PlateNumber3 = max(case when rn = 3 then PlateNumber end)
, Country1 = max(case when rn = 1 then Country end)
, Country2 = max(case when rn = 2 then Country end)
, Country3 = max(case when rn = 3 then Country end)
from (
select t.*
, rn=row_number() over (partition by PID order by platenumber)
from t
) as t
group by pid, name
返回:
+-----+-------+--------------+--------------+--------------+----------+----------+----------+
| pid | name | PlateNumber1 | PlateNumber2 | PlateNumber3 | Country1 | Country2 | Country3 |
+-----+-------+--------------+--------------+--------------+----------+----------+----------+
| 111 | Alex | ab123456 | fe123344 | r223456e | GB | ES | US |
| 113 | Ben | ve923456 | NULL | NULL | IT | NULL | NULL |
| 112 | Simon | q32345ke | t22er563 | NULL | DE | GB | NULL |
+-----+-------+--------------+--------------+--------------+----------+----------+----------+
答案 2 :(得分:0)
如果PlateNumber计数未固定为PID,则可以使用动态语句。
CREATE TABLE #tt(PID INT,[Name] VARCHAR(10),PlateNumber VARCHAR(10),Country VARCHAR(5))
INSERT INTO #tt
select 111 , 'Alex' , 'ab123456' , 'GB' union all
select 111 , 'Alex' , 'fe123344' , 'ES' union all
select 111 , 'Alex' , 'r223456e' , 'US' union all
select 112 , 'Simon' , 't22er563' , 'GB' union all
select 112 , 'Simon' , 'q32345ke' , 'DE' union all
select 113 , 'Ben' , 've923456' , 'IT'
DECLARE @SQL VARCHAR(max),@col VARCHAR(max)
---- Get the max line count of all the PID
DECLARE @MaxNumber INT =0
SELECT @MaxNumber=CASE WHEN COUNT(0)>@MaxNumber THEN count(0) ELSE @MaxNumber END FROM #tt AS t GROUP BY t.Name,t.PID
PRINT @MaxNumber
SELECT @col=ISNULL(@col+',','')+'PlateNumber'+LTRIM(sv.number)+',Country'+LTRIM(sv.number)
FROM master.dbo.spt_values AS sv WHERE sv.type='P' AND sv.number BETWEEN 1 AND @MaxNumber
PRINT @col
SET @SQL='
SELECT * FROM (
SELECT pid,[name],c.col_value,c.col_title+LTRIM(ROW_NUMBER()OVER(PARTITION BY t.PID,[name],c.col_title ORDER BY (SELECT 0))) AS col_title FROM #tt AS t
CROSS APPLY(VALUES(''PlateNumber'',t.PlateNumber),(''Country'',t.Country))c(col_title,col_value)
) AS t
PIVOT(MAX(col_value) FOR col_title IN ('+@col+')) p'
EXEC(@SQL)
pid name PlateNumber1 Country1 PlateNumber2 Country2 PlateNumber3 Country3 ----------- ---------- ------------ ---------- ------------ ---------- ------------ ---------- 111 Alex r223456e GB fe123344 ES ab123456 US 113 Ben ve923456 IT NULL NULL NULL NULL 112 Simon q32345ke DE t22er563 GB NULL NULL