【问题标题】:"Transpose-esque" - T/SQL“转置式” - T/SQL
【发布时间】:2014-02-04 18:55:57
【问题描述】:
DECLARE @TABLE TABLE (NAME varchar(10), DOB Datetime2, Location varchar(50), Phone int)
INSERT INTO @TABLE (NAME, DOB, Location, Phone)
SELECT 'Name1','2000-01-01','USA',1234567890
UNION ALL
SELECT 'Name2','2000-01-02','CAN',0987654321

SELECT * FROM @TABLE

/* 电流输出

NAME    DOB                         Location    Phone
Name1   2000-01-01 00:00:00.0000000 USA         1234567890
Name2   2000-01-02 00:00:00.0000000 CAN         987654321

期望的输出

Catagory    N1              N2          ...Nn
            'NAME1'         'Name2'
DOB         '2000-01-01'    '2000-01-02'
Location    'USA'           'CAN'
Phone       1234567890      0987654321

类别,N1,N2,...Nn 是列名(Nn = 可以有动态数量的“名称” 'Name1,'Name2',...'Namen' 没有类别名称 不知道如何正确地做到这一点......也许是 XML?请帮忙! */

谢谢

【问题讨论】:

  • 我对枢轴不熟悉,但我不需要对枢轴使用某种聚合吗?不确定我会在这种情况下使用什么聚合。---也许是反透视?现在试试。
  • select * from ( select Name, DOB, Location, Phone from @TABLE ) x pivot ( max(Phone) for Name in([Name1], [Name2]) )p -- 哈哈哈!甚至没有关闭。

标签: sql-server tsql pivot unpivot


【解决方案1】:

您可以使用 PIVOT 函数来获得结果,但您需要先使用其他一些函数才能获得最终产品。

首先,您需要为每一行创建一个唯一的序列(看起来好像没有),该值将用于创建新列的最终列表。您可以使用row_number() 创建此值:

select name, dob, location, phone,
  row_number() over(order by name) seq
from yourtable

SQL Fiddle with Demo。创建此唯一值后,您可以取消透视多列数据 namedoblocationphone。根据您的 SQL Server 版本,您可以使用 unpivot 函数或 CROSS APPLY:

select 'N'+cast(seq as varchar(10)) seq,
  category, value, so
from
(
  select name, dob, location, phone,
    row_number() over(order by name) seq
  from yourtable
) src
cross apply
(
  select 'name', name, 1 union all
  select 'DOB', convert(varchar(10), dob, 120), 2 union all
  select 'Location', location, 3 union all
  select 'Phone', cast(phone as varchar(15)), 4
) c (category, value, so);

SQL Fiddle with Demo。这将以以下格式获取您的数据:

| SEQ | CATEGORY |      VALUE | SO |
|-----|----------|------------|----|
|  N1 |     name |      Name1 |  1 |
|  N1 |      DOB | 2000-01-01 |  2 |
|  N1 | Location |        USA |  3 |
|  N1 |    Phone | 1234567890 |  4 |

现在您可以轻松应用 PIVOT 功能:

SELECT category, n1, n2 
FROM 
(
  select 'N'+cast(seq as varchar(10)) seq,
    category, value, so
  from
  (
    select name, dob, location, phone,
      row_number() over(order by name) seq
    from yourtable
  ) src
  cross apply
  (
    select 'name', name, 1 union all
    select 'DOB', convert(varchar(10), dob, 120), 2 union all
    select 'Location', location, 3 union all
    select 'Phone', cast(phone as varchar(15)), 4
  ) c (category, value, so)
) d
pivot
(
  max(value)
  for seq in (N1, N2)
) piv
order by so;

SQL Fiddle with Demo。如果您的值数量有限,上述方法非常有用,但如果您的 names 数量未知,那么您将需要使用动态 SQL:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME('N'+cast(seq as varchar(10))) 
                    from
                    (
                      select row_number() over(order by name) seq
                      from yourtable
                    )d
                    group by seq
                    order by seq
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT category, ' + @cols + ' 
            from 
            (
              select ''N''+cast(seq as varchar(10)) seq,
                category, value, so
              from
              (
                select name, dob, location, phone,
                  row_number() over(order by name) seq
                from yourtable
              ) src
              cross apply
              (
                select ''name'', name, 1 union all
                select ''DOB'', convert(varchar(10), dob, 120), 2 union all
                select ''Location'', location, 3 union all
                select ''Phone'', cast(phone as varchar(15)), 4
              ) c (category, value, so)
            ) x
            pivot 
            (
                max(value)
                for seq in (' + @cols + ')
            ) p 
            order by so'

execute sp_executesql @query;

SQL Fiddle with Demo。他们都给出了以下结果:

| CATEGORY |         N1 |         N2 |
|----------|------------|------------|
|     name |      Name1 |      Name2 |
|      DOB | 2000-01-01 | 2000-01-02 |
| Location |        USA |        CAN |
|    Phone | 1234567890 |  987654321 |

【讨论】:

  • 天哪!这将需要一些时间来摄取,但会得到所需的输出。哇!……哇!非常感谢您的宝贵时间。
猜你喜欢
  • 1970-01-01
  • 2021-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-08
  • 2015-09-27
相关资源
最近更新 更多