我正在寻找一种在SQL server中将行转换为列的有效方法,我听说PIVOT不是很快,我需要处理大量记录.

这是我的例子:

   -------------------------------
   | Id | Value  | ColumnName    |
   -------------------------------
   | 1  | John   | FirstName     |
   | 2  | 2.4    | Amount        |
   | 3  | ZH1E4A | PostalCode    |
   | 4  | Fork   | LastName      |
   | 5  | 857685 | AccountNumber |
   -------------------------------

这是我的结果:

---------------------------------------------------------------------
| FirstName  |Amount|   PostalCode   |   LastName  |  AccountNumber |
---------------------------------------------------------------------
| John       | 2.4  |   ZH1E4A       |   Fork      |  857685        |
---------------------------------------------------------------------

我如何建立结果?

推荐答案

有几种方法可以将数据从多行转换为列.

Using PIVOT

在SQL Server中,可以使用PIVOT函数将数据从行转换为列:

select Firstname, Amount, PostalCode, LastName, AccountNumber
from
(
  select value, columnname
  from yourtable
) d
pivot
(
  max(value)
  for columnname in (Firstname, Amount, PostalCode, LastName, AccountNumber)
) piv;

Demo.

Pivot with unknown number of columnnames

如果要转置的未知数字为columnnames,则可以使用动态SQL:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(ColumnName) 
                    from yourtable
                    group by ColumnName, id
                    order by id
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = N'SELECT ' + @cols + N' from 
             (
                select value, ColumnName
                from yourtable
            ) x
            pivot 
            (
                max(value)
                for ColumnName in (' + @cols + N')
            ) p '

exec sp_executesql @query;

Demo.

使用聚合函数

如果不想使用PIVOT函数,则可以使用CASE表达式的聚合函数:

select
  max(case when columnname = 'FirstName' then value end) Firstname,
  max(case when columnname = 'Amount' then value end) Amount,
  max(case when columnname = 'PostalCode' then value end) PostalCode,
  max(case when columnname = 'LastName' then value end) LastName,
  max(case when columnname = 'AccountNumber' then value end) AccountNumber
from yourtable

Demo.

使用多个连接

这也可以通过使用多个联接来完成,但是您需要一些列来关联示例数据中没有的每一行.但基本语法是:

select fn.value as FirstName,
  a.value as Amount,
  pc.value as PostalCode,
  ln.value as LastName,
  an.value as AccountNumber
from yourtable fn
left join yourtable a
  on fn.somecol = a.somecol
  and a.columnname = 'Amount'
left join yourtable pc
  on fn.somecol = pc.somecol
  and pc.columnname = 'PostalCode'
left join yourtable ln
  on fn.somecol = ln.somecol
  and ln.columnname = 'LastName'
left join yourtable an
  on fn.somecol = an.somecol
  and an.columnname = 'AccountNumber'
where fn.columnname = 'Firstname'

Sql相关问答推荐

错误ORA-00908:通过全能自动化,缺少PLSQL编译器的关键字

SQL—如何根据2列填写缺失的值

为什么Prisma生成唯一索引,而不是基于方案上的唯一列约束?

如何使用ROW_NUM() Select 一个没有第二条记录的实例?

Access 365将文本转换回BigInt

基于多列比较连接两个表

Redshift PL/pgSQL循环中的参数化列名

对于多字节字符,SQL Server中的DATALENGTH返回1字节

基于开始/结束日期重叠的BigQuery突发行

如何使用SQL生成数据的滚动3天总和

配置单元查询失败:无法识别';附近的输入;LEFT'';(select子句中的';';col'

Postgresql - WHERE 中的 MAX 标准 - 初学者问题

计算不同模式的时间跨度

如何根据创建日期查找两个表中最接近的记录?

PostgreSQL - 从同一张表中获取值

BigQuery Pivot 遗漏行

我如何编写一个遍历数组数组并将所有值连接成一个字符串的 postgres 函数

如何防止 SQL 中的负收入值并将其重新分配到接下来的月份?

Postgres:表的累积视图

如果当前日期是一周中的某一天,则从另一天提取结果