【问题标题】:Convert columns to rows and a column name in SQL Server在 SQL Server 中将列转换为行和列名
【发布时间】:2017-04-06 12:52:24
【问题描述】:

我想在 SQL Server 中将列转换为行:

Id   Value  Jan1  Jan2
----------------------
1     2      25    35
2     5      45    45

结果应该是

Id  Value Month 1  2
----------------------
1    2     Jan  25 35
2    5     Jan  45 45

我怎样才能得到这个结果?请大家帮忙

【问题讨论】:

  • 您的样本和所需结果有点薄。一年中的这些日子还是年复一年?会有几个月吗?

标签: sql sql-server sql-server-2008 sql-server-2012 sql-server-2008-r2


【解决方案1】:

你问的有点奇怪。如果我将您的示例扩展为包含 Feb1Feb2 的列,那么我会看到两个用于转置列的选项:

+----+-------+------+------+------+------+
| Id | Value | Jan1 | Jan2 | Feb1 | feb2 |
+----+-------+------+------+------+------+
|  1 |     2 |   25 |   35 |   15 |   28 |
|  2 |     5 |   45 |   45 |   60 |   60 |
+----+-------+------+------+------+------+

仅转置月份部分:

select Id, Value, MonthName, MonthValue1, MonthValue2
from t
  cross apply (values ('Jan',Jan1,Jan2),('Feb',Feb1,Feb2)
    ) v (MonthName,MonthValue1,MonthValue2)

返回:

+----+-------+-----------+-------------+-------------+
| Id | Value | MonthName | MonthValue1 | MonthValue2 |
+----+-------+-----------+-------------+-------------+
|  1 |     2 | Jan       |          25 |          35 |
|  1 |     2 | Feb       |          15 |          28 |
|  2 |     5 | Jan       |          45 |          45 |
|  2 |     5 | Feb       |          60 |          60 |
+----+-------+-----------+-------------+-------------+

或者像这样完全转置月份列:

select Id, Value, MonthName, MonthValue
from t
  cross apply (values ('Jan1',Jan1),('Jan2',Jan2),('Feb1',Feb1),('Feb2',Feb2)
    ) v (MonthName,MonthValue)

返回:

+----+-------+-----------+------------+
| Id | Value | MonthName | MonthValue |
+----+-------+-----------+------------+
|  1 |     2 | Jan1      |         25 |
|  1 |     2 | Jan2      |         35 |
|  1 |     2 | Feb1      |         15 |
|  1 |     2 | Feb2      |         28 |
|  2 |     5 | Jan1      |         45 |
|  2 |     5 | Jan2      |         45 |
|  2 |     5 | Feb1      |         60 |
|  2 |     5 | Feb2      |         60 |
+----+-------+-----------+------------+

rextester 演示:http://rextester.com/KZV45690

【讨论】:

    【解决方案2】:

    这似乎是:

    select Id, Value, 'Jan' as [month], Jan1 as [1], Jan2 as [2]
    from t;
    

    您基本上只是在输出中添加另一列。

    我不建议使用数字作为列名,也不建议使用 SQL Server 关键字,例如 month

    【讨论】:

    • ,Month 列不可用。从 SELECT 子句中删除 Month 列。
    【解决方案3】:

    这是一个您不必指定最多 365 个字段的选项

    Declare @YourTable table (Id int,Value int,Jan1 int,Jan2 int,Feb1 int, Feb2 int)
    Insert Into @YourTable values
    (1,     2,      25,    35, 100, 101),
    (2,     5,      45,    45, 200, 201)
    
    
    Select [Id],[Value],[Month],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31]
     From (
            Select A.Id
                  ,A.Value
                  ,[Month]   = Left(C.Item,3)
                  ,[Col]     = substring(C.Item,4,5)
                  ,[Measure] = C.Value
             From  @YourTable A
             Cross Apply (Select XMLData = cast((Select A.* for XML Raw) as xml)) B
             Cross Apply (
                            Select Item   = attr.value('local-name(.)','varchar(100)')
                                  ,Value  = attr.value('.','int') 
                             From  B.XMLData.nodes('/row') as A(r)
                             Cross Apply A.r.nodes('./@*') AS B(attr)
                             Where attr.value('local-name(.)','varchar(100)') not in ('ID','Value')
                         ) C
          ) A
     Pivot (sum(Measure) For [Col] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31]) ) p
    

    退货

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-01
      • 1970-01-01
      • 2021-02-24
      • 2010-10-22
      相关资源
      最近更新 更多