SQL Server 2008 中 PIVOT 的更新

如果没有聚合,有没有办法在 SQL Server 2008 中对 PIVOTed 表执行更新,其中更改传播回源表?

Is there a way to perform updates on a PIVOTed table in SQL Server 2008 where the changes propagate back to the source table, assuming there is no aggregation?

推荐答案

这只有在透视列形成唯一标识符时才真正起作用.那么让我们以Buggy的例子为例;这是原始表格:

This will only really work if the pivoted columns form a unique identifier. So let's take Buggy's example; here is the original table:

TaskID    Date    Hours

我们想把它转成一个如下所示的表格:

and we want to pivot it into a table that looks like this:

TaskID    11/15/1980    11/16/1980    11/17/1980 ... etc.

为了创建枢轴,您可以执行以下操作:

In order to create the pivot, you would do something like this:

DECLARE @FieldList NVARCHAR(MAX)

SELECT
    @FieldList =
    CASE WHEN @FieldList <> '' THEN 
        @FieldList + ', [' + [Date] + ']' 
    ELSE 
        '[' + [Date] + ']' 
    END
FROM
    Tasks



DECLARE @PivotSQL NVARCHAR(MAX)
SET @PivotSQL = 
    '
        SELECT 
            TaskID
            , ' + @FieldList + '
        INTO
            ##Pivoted
        FROM 
            (
                SELECT * FROM Tasks
            ) AS T
        PIVOT
            (
                MAX(Hours) FOR T.[Date] IN (' + @FieldList + ') 
            ) AS PVT
    '

EXEC(@PivotSQL)

那么你在 ##Pivoted 中有你的透视表.现在您对小时字段之一执行更新:

So then you have your pivoted table in ##Pivoted. Now you perform an update to one of the hours fields:

UPDATE
    ##Pivoted
SET
    [11/16/1980 00:00:00] = 10
WHERE
    TaskID = 1234

现在 ##Pivoted 有一个更新版本的小时数,该任务发生在 1980 年 11 月 16 日,我们希望将其保存回原始表,因此我们使用 UNPIVOT:

Now ##Pivoted has an updated version of the hours for a task that took place on 11/16/1980 and we want to save that back to the original table, so we use an UNPIVOT:

DECLARE @UnPivotSQL NVarChar(MAX)
SET @UnPivotSQL = 
    '
        SELECT
              TaskID
            , [Date]
            , [Hours]
        INTO 
            ##UnPivoted
        FROM
            ##Pivoted
        UNPIVOT
        (
            Value FOR [Date] IN (' + @FieldList + ')
        ) AS UP

    '

EXEC(@UnPivotSQL)

UPDATE
    Tasks
SET
    [Hours] = UP.[Hours]
FROM
    Tasks T
INNER JOIN
    ##UnPivoted UP
ON
    T.TaskID = UP.TaskID

您会注意到我修改了 Buggy 的示例以删除按星期几的聚合.那是因为如果您执行任何类型的聚合,就没有回头路和更新.如果我更新 SUNHours 字段,我如何知道我正在更新哪个星期日的时间?这仅在没有聚合的情况下才有效.我希望这会有所帮助!

You'll notice that I modified Buggy's example to remove aggregation by day-of-week. That's because there's no going back and updating if you perform any sort of aggregation. If I update the SUNHours field, how do I know which Sunday's hours I'm updating? This will only work if there is no aggregation. I hope this helps!

相关文章