SQL Join Query - Group By / Aggregation

时间:2012-10-08 13:03:18

标签: sql sql-server sql-server-2005 pivot unpivot

我意识到此问题之前曾以多种形式提出,但我很难将我找到的每个答案都应用到我的特定表格中。首先 - 直接了解细节。

表A有四列(唯一ID,编号,修订版,日期)。从A执行select *时,结果集如下 -

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

我希望每个修订版的日期在每个数字的单行中,例如对于编号12345,查询将返回

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|

我理解语法类似于

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

然而,对于每个组合,这仍然会返回一行,我想只显示上面显示的结果。

我很感激任何建议或提示!

1 个答案:

答案 0 :(得分:2)

您可以同时使用UNPIVOTPIVOT来完成此操作。如果您有一定数量的值要转换为列,那么您可以使用STATIC PIVOT并对值进行硬编码:

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

请参阅SQL Fiddle with Demo

如果您有不确定数量的值,则需要使用动态SQL来PIVOT数据。

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)

请参阅SQL Fiddle With demo