重新格式化SQL Server表列名称和数据透视表

时间:2017-12-30 15:28:54

标签: sql sql-server tsql

我有一个存储在SQL Server数据库中的表,其中包含用户ID,产品名称和按行存储在列中的值。这几周的列名称如下所示" trx_2015#08#07"并且该周的值存储在每列中:

UserId, ProductName, trx_2015#08#07, trx_2015#08#014, trx_2015#08#21

我想清理那些列名(我不能改变表格)只是周值(2015-08-07),然后将数据转换为这种格式:

userID, ProductName, Week, Value

对最简单的方法有任何想法吗?

1 个答案:

答案 0 :(得分:1)

SQL Server提供了一种使用UNPIVOT relational operator按照您的意愿操作数据的方法。以下是除了动态获取列名之外如何实现此目的的示例(理想情况下,我们不希望每次添加列时都更新查询)。

答案的架构/数据设置

CREATE TABLE tbl (
  UserId INT,
  ProductName NVARCHAR(1000),
  [trx_2015#08#07] INT,
  [trx_2015#08#014] INT,
  [trx_2015#08#21] INT
);

INSERT INTO tbl(UserId, ProductName, [trx_2015#08#07], [trx_2015#08#014], [trx_2015#08#21])
VALUES (1, 'Product #1', 123, 456, 789);

动态获取trx列名称

我们需要将trx colmn名称的聚合连接传递给UNPIVOT关系overator的IN子句。

SELECT STUFF((SELECT ',' + QUOTENAME(COLUMN_NAME)
  FROM INFORMATION_SCHEMA.COLUMNS
  WHERE 
    TABLE_NAME = 'tbl'
    AND COLUMN_NAME LIKE 'trx_%'
  FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '')

构建查询

最终,我们希望查询看起来像这样:

SELECT UserId, ProductName, Value, trx 
FROM tbl 
  UNPIVOT(
    Value FOR trx IN ([trx_2015#08#014],[trx_2015#08#07],[trx_2015#08#21])
  ) AS unpvt

查询必须在SQL中动态构建,因为此处的IN子句不能接受结果集。

<强>查询:

DECLARE @SQLString NVARCHAR(MAX);
SET @SQLString = CONCAT(
  'SELECT UserId, ProductName, Value, trx FROM tbl UNPIVOT(Value FOR trx IN (', 
  (SELECT STUFF((SELECT ',' + QUOTENAME(COLUMN_NAME)
  FROM INFORMATION_SCHEMA.COLUMNS
  WHERE 
    TABLE_NAME = 'tbl'
    AND COLUMN_NAME LIKE 'trx_%'
  FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '')), 
  ')) AS unpvt'
);

EXEC(@SQLString);

结果集:

UserId  ProductName Value   trx
1       Product #1  456     trx_2015#08#014
1       Product #1  123     trx_2015#08#07
1       Product #1  789     trx_2015#08#21