【问题标题】:SQL Join Query - Group By / AggregationSQL 连接查询 - 分组方式/聚合
【发布时间】:2012-09-28 17:46:28
【问题描述】:

我意识到这个问题以前曾以多种形式提出过,但我正在努力将我找到的每一个答案都应用到我的特定表格中。开始 - 直接进入细节。

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

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

但是这仍然为每个组合返回一行,我只想要上面显示的结果。

如果有任何建议或提示,我将不胜感激!

【问题讨论】:

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


【解决方案1】:

您可以同时使用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

【讨论】:

  • 太棒了!谢谢,一个问题,虽然每个日期都是空的,当我从 mytable 运行 select convert(varchar(10), date, 120) date 时,日期很好,但是在这两个查询中(第二个动态查询,有根本没有日期列)日期都为空。
  • @user1142132 你能用一些示例数据创建一个SQL Fiddle 供我查看吗?使用你的样本我没有得到任何空日期——sqlfiddle.com/#!3/67d11/21
  • 我创建了一个 sqlfiddle 来复制我的表和一些示例数据,但我没有得到其中的空日期sqlfiddle.com/#!3/8706a/1,但是这是我在 sql server i.imgur.com/Qx4oN.png 中的结果的屏幕截图
  • @user1142132 你能在 sql fiddle 上创建一个更大的数据样本吗?只有两行数据很难分辨
  • 抱歉,我又添加了一些,日期仍然出现,如果您需要更大的样本,请告诉我。
猜你喜欢
  • 1970-01-01
  • 2011-12-15
  • 2023-02-03
  • 2017-08-20
  • 1970-01-01
  • 2023-03-06
  • 2014-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多