znedw
znedw

Reputation: 1

SQL Join Query - Group By / Aggregation

I realise this question has been asked before in many forms but I am struggling to apply every answer I've found to my specific table. To start - straight to the details.

Table A has four columns (Unique ID, Number, Revision, Date). When executing a select * from A, the result set is as follows -

ID | Number | Revision | Date
------------------------------------
01 | 12345  | 1        | 01/01/2010
02 | 12345  | 2        | 01/04/2010
03 | 123    | 1        | 01/12/2010
04 | 1234   | 1        | 09/09/2012
05 | 12345  | 3        | 09/12/2012

I would like the dates for each Revision in a single row per Number, e.g. for Number 12345, the query would return

ID | Number | Revision | Date | Revision 2 | Revision 2 Date | Revision 3 | Revision 3 Date |
---------------------------------------------------------------------------------------------
01 | 12345  | 1 | 01/01/2010 |2  | 01/04/2010      | 3 |  09/12/2012|

I understand the syntax would be similar to

SELECT Revision, Date 
FROM (
SELECT NUMBER 
FROM A) as B INNER JOIN ON a.Number = B.Number 
GROUP BY a.Number

However this still returns a row for each combination, I would like only the results shown above.

I would appreciate any suggestions or hints!

Upvotes: 0

Views: 199

Answers (1)

Taryn
Taryn

Reputation: 247720

You can use both an UNPIVOT and then a PIVOT to accomplish this. If you have a known number of values to convert to column, then you can use a STATIC PIVOT and hard-code the values:

select number, [revision_1], [date_1],
             [revision_2], [date_2],
             [revision_3], [date_3]
from
(
  select number, value,
    col + '_' + cast(rn as varchar(10)) col
  from
  (
    select id, number, cast(revision as varchar(10)) revision, 
      convert(varchar(10), date, 120) date,
      row_number() over(partition by number order by date) rn
    from yourtable
  ) x
  unpivot
  (
    value
    for col in (revision, date)
  ) u
) x1
pivot
(
  max(value)
  for col in ([revision_1], [date_1],
             [revision_2], [date_2],
             [revision_3], [date_3])
)p

See SQL Fiddle with Demo

If you have an unknown number of values, then you will need to use dynamic SQL to PIVOT the data.

DECLARE @query  AS NVARCHAR(MAX),
    @colsPivot as  NVARCHAR(MAX)


select @colsPivot = STUFF((SELECT  ',' 
                      + quotename(c.name + '_'
                         + cast(t.rn as varchar(10)))
                    from
                    (
                      select row_number()
                        over(partition by number order by date) rn
                      from yourtable
                    ) t
                    cross apply 
                      sys.columns as C
                   where C.object_id = object_id('yourtable') and
                         C.name in ('Revision', 'date')
                   group by c.name, t.rn
                   order by t.rn
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query 
  = 'select *
      from
      (
          select number, value,
            col + ''_'' + cast(rn as varchar(10)) col
        from 
        (
          select id, number, cast(revision as varchar(10)) revision, 
            convert(varchar(10), date, 120) date,
            row_number() over(partition by number order by date) rn
          from yourtable
        ) x
        unpivot
        (
          value
          for col in (revision, date)
        ) u
      ) x1
      pivot
      (
        max(value)
        for col in ('+ @colspivot +')
      ) p'

exec(@query)

See SQL Fiddle With demo

Upvotes: 2

Related Questions