Sql server 具有动态字段类型的Sql server动态透视

Sql server 具有动态字段类型的Sql server动态透视,sql-server,dynamic,type-conversion,field,pivot,Sql Server,Dynamic,Type Conversion,Field,Pivot,我需要在SQLServer2005上构建一个动态数据透视表,我找到了几个关于如何实现的很好的答案,但我需要实现一个额外的要求:动态字段类型 这是我的数据结构 CREATE TABLE [dbo].[MyData]( [Key] [char](12) NOT NULL, [AttributeName] [char](3) NOT NULL, [AttributeValue] [char](40) NOT NULL) 这是类型的定义 CREATE TABLE [dbo].[Attributes](

我需要在SQLServer2005上构建一个动态数据透视表,我找到了几个关于如何实现的很好的答案,但我需要实现一个额外的要求:动态字段类型

这是我的数据结构

CREATE TABLE [dbo].[MyData](
[Key] [char](12) NOT NULL,
[AttributeName] [char](3) NOT NULL,
[AttributeValue] [char](40) NOT NULL)
这是类型的定义

CREATE TABLE [dbo].[Attributes](
[AttributeName] [char](3) NOT NULL,
[CastTo] [char](10) NOT NULL,
[Size] int NULL,
[Precision] int NULL)
这是预期的结果:

KEY  | 001 (of type found in tab Attributes) | 002          | 003    |004         |...
---------------------------------------------------------------------------------------
k1   | I am a Varchar                          |  12345.789 | 0 (bit)| 2014-10-02 |...
MyData可以包含大约100000个不同的键和大约500个不同的AttributeName

以下是一些示例数据:

INSERT [MyAttributes] ([AttributeName], [CastTo], [Size], [Precision]) VALUES (N'001', N'varchar   , 10, NULL)
GO
INSERT [MyAttributes] ([AttributeName], [CastTo], [Size], [Precision]) VALUES (N'002', N'int       ', NULL, NULL)
GO
INSERT [MyAttributes] ([AttributeName], [CastTo], [Size], [Precision]) VALUES (N'003', N'datetime  ', NULL, NULL)
GO
INSERT [MyAttributes] ([AttributeName], [CastTo], [Size], [Precision]) VALUES (N'004', N'decimal   ', 10, 4)
GO
INSERT [MyData] ([Key], [AttributeName], [AttributeValue]) VALUES (N'k1', N'001', N'abcd                                    ')
GO
INSERT [MyData] ([Key], [AttributeName], [AttributeValue]) VALUES (N'k1', N'002', N'111                                     ')
GO
INSERT [MyData] ([Key], [AttributeName], [AttributeValue]) VALUES (N'k1', N'003', N'20150102                                ')
GO
INSERT [MyData] ([Key], [AttributeName], [AttributeValue]) VALUES (N'k1', N'004', N'12345.1                                 ')
GO
INSERT [MyData] ([Key], [AttributeName], [AttributeValue]) VALUES (N'k2', N'001', N'efgh                                    ')
GO
INSERT [MyData] ([Key], [AttributeName], [AttributeValue]) VALUES (N'k2', N'002', N'222                                     ')
GO
INSERT [MyData] ([Key], [AttributeName], [AttributeValue]) VALUES (N'k3', N'003', N'20121212                                ')
GO
对于MyData表中的每个不同键,我必须创建一个记录,其中键作为第一个字段,然后对于每个不同的AttributeName,我必须在Attributes表中查找适当的类型、大小和精度,输出一个名为[AttributeName]的适当类型的字段,并将[AttributeValue]强制转换为适当的类型


这可以使用Pivot来完成吗?或者使用for XML子句的一些技巧可以帮助考虑字段类型?除了自定义存储过程之外,我不知道如何生成大量动态sql,但它不容易回收,可能难以维护且效率低下。

我发现了这个可行的解决方案

它还不完整(缺少varchar的大小和数字类型的精度),但它已经足够让人明白这一点。 转换不能在pivot部分上完成,当然在查询源表时也不能工作,因为类型是混合的。 我找到的解决方案是将强制转换添加到动态列列表中,为pivot创建一个更简单的列表(仅字段名),为mainselect创建一个更长的列表(包括强制转换)

DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX), @ColumnsShort nVarChar(MAX);
SET @columnsShort = '';
SELECT @columnsShort  = @columnsShort + N', p.' + QUOTENAME(AttributeName)
  FROM (SELECT distinct p.AttributeName FROM MyData AS p
  INNER JOIN MyAttributes AS o
ON rtrim(p.AttributeName) = rtrim(o.AttributeName)
  ) AS x;

SET @columns = '';
SELECT @columns  = @columns + N', ' + attr
  FROM (SELECT distinct 'CAST(' + QUOTENAME(p.AttributeName) + ' AS ' + o.CastTo + ') AS ' + QUOTENAME(p.attributename) as attr FROM MyData AS p
  INNER JOIN MyAttributes AS o
ON rtrim(p.AttributeName) = rtrim(o.AttributeName)
  ) AS x;

SET @sql = N'
SELECT  [Key], ' + STUFF(@columns, 1, 2, '') + '
FROM
(
  SELECT [key], p.AttributeName, attributevalue
   FROM dbo.MyData AS p
   INNER JOIN dbo.MyAttributes AS o
   ON rtrim(p.AttributeName) = rtrim(o.AttributeName)
) AS j
PIVOT
(
 max(AttributeValue) FOR AttributeName IN ('
  + STUFF(REPLACE(@columnsshort, ', p.[', ',['), 1, 1, '')
  + ') 
) AS p;';
PRINT @sql;

execute sp_executesql @sql

既然您已经在编写动态代码,为什么不像“CAST”(“+AttributeValue+”和“+Type+”)那样简单,不添加您的
dynamic pivot
查询。尝试添加CAST时,我做错了一些事情:为了进一步澄清,您正在尝试将
max(AttributeValue)
转换为
CAST(AttributeValue为o.[Type])
在pivot()中?这就是我所理解的。是的@user1237854你明白了。我发现一个解决方案贴在了自我回答栏上。它既不完整也不优化,但为进一步细化提供了一个良好的起点。