2012-05-24 3 views
0

다음 SQL 쿼리에 병합 문을 도입하여 레코드를 테이블 스냅 샷으로 업데이트하거나 기존 레코드 기반과 비교할 수있는 일치 여부에 따라 삽입하려고했습니다. BuildingId 및 타임 스탬프.SQL Server - 선택 쿼리에서 병합 삽입/업데이트

기본적으로 쿼리는 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); 
+0

MERGE 문을 사용하거나 "upsert"를 수행하려고합니까? –

답변

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의 필터는 업데이트에서 필터를 제거합니다.

+1

내 게시물의 서식을 지정했습니다. 나도 태블릿에있어. :-) –