【问题标题】:Dynamic casting when using pivot使用枢轴时的动态投射
【发布时间】:2014-11-12 12:13:07
【问题描述】:

我正在使用 EAV 模式将任意数据存储在单个表中 (Entries)。 Data 存储为nvarchar 并通过PropertyID 链接目标数据类型。现在我想创建一个视图来使用数据透视重构数据,但我无法将Data 动态转换为它的预期数据类型。执行下面的查询,我得到错误#8114 error converting data type nvarchar to float

这本质上是我的数据库结构:

EntryID | PropertyID | Data (nvarchar)
----------------------------
1       | 1          | 1
2       | 2          | abc
3       | 3          | 2.0
....


PropertyID | PropertyName | TypeID
------------------------------------
1          | intProp      | 1
2          | strProp      | 2
3          | fltProp      | 3
....

TypeID | TypeName
-----------------
1      | int
2      | string
3      | float
4      | bool
5      | datetime
....

这是查询:

SELECT [intProp], [strProp], [fltProp]
FROM
(
    SELECT e.EntryID, p.PropertyName, 

        CASE 
            WHEN t.TypeName = 'int' THEN
                CAST(e.data as int)
            WHEN t.TypeName = 'float' THEN
                CAST(e.data as float)
            WHEN t.TypeName = 'string' THEN
                e.data

        END as converted

    FROM 
        Entries e 
        INNER JOIN Properties p ON e.PropertyID = p.PropertyID
        INNER JOIN Types t ON p.TypeID = t.TypeID           
) as t1
PIVOT
(
    MAX(converted)
    FOR PropertyName IN ( [intProp], [strProp], [fltProp])
) as piv

显然CASE 语句是问题所在,但是如何将查询转换为动态转换为正确的数据类型?

【问题讨论】:

  • 您需要在枢轴之后进行强制转换,但您不能动态地执行此操作。你只能做CAST(piv.[intProp] AS INT)。您遇到了EAV 被视为 SQL 反模式的原因之一。
  • 这可能有助于解决您的问题:stackoverflow.com/questions/27744532/…>

标签: sql sql-server sql-server-2008-r2 pivot entity-attribute-value


【解决方案1】:

根据我之前的评论,我尝试创建一个可能对您有所帮助的 SQL 脚本:

    DECLARE @colsConversion as NVARCHAR(MAX), @query AS NVARCHAR(MAX)
    SELECT @colsConversion = STUFF((SELECT ',CAST('+QuoteName(p.PropertyName)+' as '+t.TypeName+') as '+QuoteName(p.PropertyName)
    FROM  Properties  p 
    INNER JOIN Types t ON p.TypeID = t.TypeID
    GROUP BY p.PropertyName, t.TypeName
    FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,1,'')



SET @query = 'SELECT ' + @colsConversion +'
FROM
(
    SELECT e.EntryID,p.PropertyName,t.TypeName
    ,e.Data
    FROM Entries e
    INNER JOIN Properties p ON e.PropertyID = p.PropertyID
    INNER JOIN Types t ON p.TypeID = t.TypeID
)AS T1
PIVOT
(
    MAX(Data)
    FOR PropertyName in ([intProp],[strProp],[fltProp])
)as piv'

exec sp_executesql @query

【讨论】:

  • 这对我有用!我继续创建了两个变量,以便我可以保持我的列名动态。因此,除了@colsConversion,我还使用SELECT @cols = COALESCE(@cols + ',', '') + QUOTENAME(custom_data_name) 代替PIVOT 命令中的in 语句。感谢分享!
猜你喜欢
  • 1970-01-01
  • 2012-07-11
  • 2017-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-26
相关资源
最近更新 更多