SQL Server - 从Select查询合并插入/更新

时间:2012-05-24 00:35:27

标签: sql-server sql-server-2008

我一直在尝试将Merge语句引入以下SQL查询,以便将记录更新或插入表快照,具体取决于是否可以针对基于BuildingId和Timestamp的现有记录找到匹配项。

基本上,查询通过基于BuildingId获取Snapshot表中的最新记录来创建基于小时时间帧的记录快照,并且它们会计算该小时内的所有值。

-- DECLARE TABLE VARIABLES TO HOLD TEMP DATA
    DECLARE @Output table
    (
      SnapshotId bigint,
      BuildingId bigint,
      [TimeStamp] datetime
    );

-- INSERT ACCUMULATIVE SNAPSHOT DATA INTO BMS_Snapshot TABLE
        ;WITH Snap (BuildingId, Timestamp_Actual, TimestampRange_Start, TimestampRange_End) AS
            (SELECT BMS_Snapshot.BuildingId,  MAX(BMS_Snapshot.Timestamp) AS Timestamp_Actual, 
                dateadd(hh, datediff(hh,0, MAX(BMS_Snapshot.Timestamp)), 0) AS TimestampRange_Start,
                dateadd(mi, +59 , dateadd(hh, datediff(hh,0, MAX(BMS_Snapshot.Timestamp)), 0)) AS TimestampRange_End
                FROM BMS_Snapshot
                GROUP BY BMS_Snapshot.BuildingId)
            INSERT INTO BMS_Snapshot 
                (BuildingId, Timestamp, Emissions, EnergyUse, NABERS, Lighting, Heating,
                    Cooling, InternalEquipment, Fans, WaterSystems, NotClassified, Electricity,
                    Gas, Water, Other, [Range])
            OUTPUT inserted.SnapshotId, inserted.BuildingId, inserted.TimeStamp INTO @Output
            SELECT  [Snapshot].BuildingId,
                MAX(TimestampRange_End) AS Timestamp,
                SUM([Snapshot].Emissions) AS Emissions,
                SUM([Snapshot].EnergyUse) AS EnergyUse,
                AVG([Snapshot].NABERS) AS NABERS,
                SUM([Snapshot].Lighting) AS Lighting,
                SUM([Snapshot].Heating) AS Heating,
                SUM([Snapshot].Cooling) AS Cooling,
                SUM([Snapshot].InternalEquipment) AS InternalEquipment,
                SUM([Snapshot].Fans) AS Fans,
                SUM([Snapshot].WaterSystems) AS WaterSystems,
                SUM([Snapshot].NotClassified) AS NotClassified,
                SUM([Snapshot].Electricity) AS Electricity,
                SUM([Snapshot].Gas) AS Gas,
                SUM([Snapshot].Water) AS Water,
                SUM([Snapshot].Other) AS Other,
                1 AS [Range]
            FROM
                Snap INNER JOIN 
                BMS_Snapshot AS [Snapshot] ON Snap.BuildingId = [Snapshot].BuildingId
            WHERE 
                /* RANGE - FILTER ONLY 10 MINUTE SNAPSHOTS */
                [Snapshot].[Range] = 0 AND
                [Snapshot].[TimeStamp]
                BETWEEN TimestampRange_Start AND TimestampRange_End
            GROUP BY [Snapshot].BuildingId

我已经尝试将合并声明放在一起,但似乎可以让更新与“从...选择”

感谢。

编辑:

经过一些游戏后,我现在有了以下查询,如果它存在,它会更新正确的记录,但如果它不存在则不会插入:

    -- INSERT ACCUMULATIVE SNAPSHOT DATA INTO BMS_Snapshot TABLE
    ;WITH Snap (BuildingId, Timestamp_Actual, TimestampRange_Start, TimestampRange_End) AS
        (SELECT BMS_Snapshot.BuildingId,  MAX(BMS_Snapshot.Timestamp) AS Timestamp_Actual, 
            dateadd(hh, datediff(hh,0, MAX(BMS_Snapshot.Timestamp)), 0) AS TimestampRange_Start,
            dateadd(mi, +59 , dateadd(hh, datediff(hh,0, MAX(BMS_Snapshot.Timestamp)), 0)) AS TimestampRange_End
            FROM BMS_Snapshot
            GROUP BY BMS_Snapshot.BuildingId)
        MERGE INTO BMS_Snapshot AS t
            USING
                (SELECT [Snapshot].BuildingId,
                    MAX(TimestampRange_End) AS Timestamp,
                    SUM([Snapshot].Emissions) AS Emissions,
                    SUM([Snapshot].EnergyUse) AS EnergyUse,
                    AVG([Snapshot].NABERS) AS NABERS,
                    SUM([Snapshot].Lighting) AS Lighting,
                    SUM([Snapshot].Heating) AS Heating,
                    SUM([Snapshot].Cooling) AS Cooling,
                    SUM([Snapshot].InternalEquipment) AS InternalEquipment,
                    SUM([Snapshot].Fans) AS Fans,
                    SUM([Snapshot].WaterSystems) AS WaterSystems,
                    SUM([Snapshot].NotClassified) AS NotClassified,
                    SUM([Snapshot].Electricity) AS Electricity,
                    SUM([Snapshot].Gas) AS Gas,
                    SUM([Snapshot].Water) AS Water,
                    SUM([Snapshot].Other) AS Other,
                    1 AS [Range]
                FROM
                    Snap INNER JOIN 
                    BMS_Snapshot AS [Snapshot] ON Snap.BuildingId = [Snapshot].BuildingId
                WHERE 
                    /* RANGE - FILTER ONLY 10 MINUTE SNAPSHOTS */
                    [Snapshot].[Range] = 0 AND
                    [Snapshot].[TimeStamp]
                    BETWEEN TimestampRange_Start AND TimestampRange_End
                GROUP BY [Snapshot].BuildingId) As s
            ON t.BuildingId = s.BuildingId
            WHEN MATCHED AND (t.Timestamp = s.Timestamp AND
                t.[Range] = 1) THEN
                    UPDATE SET
                        t.Emissions = s.Emissions,
                        t.EnergyUse = s.EnergyUse,
                        t.NABERS = s.NABERS,
                        t.Lighting = s.Lighting,
                        t.Heating = s.Heating,
                        t.Cooling = s.Cooling,
                        t.InternalEquipment = s.InternalEquipment,
                        t.Fans = s.Fans,
                        t.WaterSystems = s.WaterSystems,
                        t.NotClassified = s.NotClassified,
                        t.Electricity = s.Electricity,
                        t.Gas = s.Gas,
                        t.Water = s.Water,
                        t.Other = s.Other
                WHEN NOT MATCHED BY t THEN
                    INSERT 
                        (BuildingId, Timestamp, EnergyUse, NABERS, Lighting, Heating,
                        Cooling, InternalEquipment, Fans, WaterSystems, NotClassified,
                        Electricity, Gas, Water, Other, [Range])
                    VALUES
                        (s.BuildingId, s.Timestamp, s.EnergyUse, s.NABERS, s.Lighting, s.Heating,
                        s.Cooling, s.InternalEquipment, s.Fans, s.WaterSystems, s.NotClassified,
                        s.Electricity, s.Gas, s.Water, s.Other, 1);

1 个答案:

答案 0 :(得分:4)

MERGE BMS_Snapshot target USING (SELECT BMS_Snapshot.BuildingID, ...) 
 source(BuildingID,...)
  ON target.BuildingID = source.BuildingID 
  AND target.Timestamp = source.Timestamp 
WHEN MATCHED THEN 
    UPDATE SET Emissions = source.Emissions, ... 
WHEN NOT MATCHED BY target THEN 
    INSERT (BuildingID, ...) 
    VALUES (source.BuildingID, ...);

我为这种格式道歉,因为我现在正在平板电脑上。

根据您的更新,您只在ON子句中查看buildingid,但您还需要时间戳。 buildingid匹配,但WHEN MATCHED上的过滤器将其从更新中删除。