SQL Pivot或其他多个字段值的解决方案,用于从子表值返回单个对象

时间:2014-02-05 02:47:52

标签: sql tsql

首先;只是为了让它不受影响:)我已经获得了一些工作表,它们是不可更改的。

主表名为Content,单行= 1条内容。添加到它的所有第一级动态字段(通过其自己的表中的动态构建的内容类型)位于名为FieldValues的子表中,该子表具有针对特定值类型的多个字段,具体取决于字段本身:FieldStringValue,FieldDecimalValue,FieldLongValue,FieldDateValue, FieldBoolValue。标识映射通过ReferenceName字段处理,该字段是在构建内容类型本身时添加的唯一名称。

想要的是返回单行内容'对象',子表行作为具有各自值的字段。

到目前为止,我有这个SQL,我只需要字符串值:

SELECT C.Id,C.ContentTypeId , Fields.*
FROM Contents AS C
OUTER APPLY (
    SELECT * FROM (
        SELECT ReferenceName,FieldStringValue
        FROM FieldValues
        WHERE ReferenceName IN (
            'recipename','recipenamehtml','url','introblurb','linkcopy','serves','makes','prep','cook','imgsetland','imgsetport'
        )
        AND ContentId = C.Id
    ) AS FieldList
    PIVOT (
        MAX(FieldStringValue)
        FOR ReferenceName IN (
            recipename, recipenamehtml, url, introblurb, linkcopy, serves, makes, prep, cook, imgsetland, imgsetport
        )
    ) AS PIV
) AS Fields
WHERE C.Id = 930 AND C.ContentTypeId = 2

但是我对如何为FieldDecimalValue“添加”检查感到有点困惑 - 我是不是以错误的方式去做?例如,如何使用FieldDecimalValue而不是FieldStringValue的值添加参考名称为“energy,calories,carbs,protein,dietryfibre,fat,satfat,sugar”的字段?

我想将表扫描保持一次通过,这就是为什么我试图通过在单个查询上使用数据透视来实现这一点 - 至少执行计划对我来说没问题:)

编辑:服务器是SQL Server 2012,任何特定于t-sql的技巧都可以。另外我意识到我可以用FieldDecimalValue重复OUTER APPLY部分,但是执行计划显示2个表扫描以获取数据,这是id想找到解决办法(如果可能的话)

1 个答案:

答案 0 :(得分:1)

这似乎有用 - 不敢相信我之前没有想到它:)。

只有'问题'是所有结果字段都将作为一种数据类型返回,除非我再次手动转换回来。但它似乎导致单个表扫描。

如果有人有这些建议,仍然可以提供更好的查询建议。

SELECT C.Id,C.ContentTypeId , Fields.*
FROM Contents AS C
OUTER APPLY (
    SELECT * FROM (
        SELECT ReferenceName,CASE
                WHEN ReferenceName IN ('energy', 'calories', 'carbs', 'protein', 'dietryfibre', 'fat', 'satfat', 'sugar') THEN CAST(FieldDecimalValue AS nvarchar(MAX))
                ELSE FieldStringValue
            END AS FSV
        FROM FieldValues
        WHERE ReferenceName IN (
            'recipename','recipenamehtml','url','introblurb','linkcopy','serves','makes','prep','cook','imgsetland','imgsetport'
            , 'energy', 'calories', 'carbs', 'protein', 'dietryfibre', 'fat', 'satfat', 'sugar'
        )
        AND ContentId = C.Id
    ) AS FieldList
    PIVOT (
        MAX(FSV)
        FOR ReferenceName IN (
            recipename, recipenamehtml, url, introblurb, linkcopy, serves, makes, prep, cook, imgsetland, imgsetport
            , energy, calories, carbs, protein, dietryfibre, fat, satfat, sugar
        )
    ) AS PIV
) AS Fields
WHERE C.Id = 930 AND C.ContentTypeId = 2