I have been trying to introduce a Merge statement into the following SQL query to either update or insert a record into a table Snapshot depending if a match can be found against an existing record based on BuildingId and Timestamp.
Essentially, the query creates a snapshot of records based on an hour time frame, by getting the latest record in the Snapshot table based on BuildingId, and them SUMs all the values that fall within that hour.
-- 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
I’ve tried putting together the merge statement, but can seem to be able to get the update to work with a ‘Select From…’
Thanks.
EDIT:
After some playing around, I now have the following query, which does update the correct record if it exists, but does not insert if it does not exist:
-- 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);
I apologize for the format, as I’m on a tablet at the moment.
per your update, you are only looking at buildingid in the ON clause, but you also need your timestamp. The buildingid matches but the filter on the WHEN MATCHED eliminates it from the update.