0

I am new with SQL Pivot, so i would like to have a detail explaination regarding to it. My table is like the following:

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      |
------------------------------------------

And i would to have the result in the following format:

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     |         |        |
--------------------------------------------------------------------------------

Could you please help me with this?

Thank you in advance!

1
  • thank you guys for your answer, i havent got chance to try it out. but i will see how it goes Commented Mar 9, 2017 at 11:09

3 Answers 3

1

The traditional cross tab / conditional aggregation version would be like so:

test setup: 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

returns:

+-----+-------+--------------+--------------+--------------+----------+----------+----------+
| 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     |
+-----+-------+--------------+--------------+--------------+----------+----------+----------+
Sign up to request clarification or add additional context in comments.

7 Comments

Didn't even realize that. +1
@GurV you should restore your answer though, it was the only way to do it with pivot().
@SqlZim, Can i ask you how to insert this into a table? i have tried put select * into table a from (this query) but it does not work :(
@Zilin If table_a exists, then use insert into table_a (...) select... If table_a doesn't exist, use select ... into table_a from ...
@SqlZim yeah, table a doesnt exist, thats why im using select * into table a from (the query), but it doesnt work, do you know what could possible cause this?
|
1

Using 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;

Demo

1 Comment

this might mix up the platenumber with the country in which it was issued (if that is even a thing with this question). keeping the same order by will prevent that.
0

If the PlateNumber count is not fixed of PID, you can use dynamic statement.

    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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.