Need to update rows from a stored procedure via IDs in a temp table

后端 未结 1 1273
挽巷
挽巷 2021-01-28 06:23

I\'m trying to take rows in a table describing outages and break them, via a calculated time range, into separate rows to be inserted into another table to describe hour by hour

相关标签:
1条回答
  • 2021-01-28 06:46

    First, some set up:

    USE tempdb;
    GO
    
    CREATE TABLE dbo.Outages
    (
        OutageDate DATE,
        StartTime TIME(7),
        EndTime TIME(7),
        Duration INT
    );
    
    INSERT dbo.Outages SELECT '20101110', '16:00', '17:30', 90;
    /*
    -- I also tested these cases, and *think* it still produces what you expect:
    INSERT dbo.Outages SELECT '20101111', '13:00', '14:02', 62;
    INSERT dbo.Outages SELECT '20101112', '17:00', '18:00', 60;
    INSERT dbo.Outages SELECT '20101113', '16:05', '16:25', 20;
    INSERT dbo.Outages SELECT '20101114', '16:59', '18:01', 62;
    INSERT dbo.Outages SELECT '20101115', '22:15', '01:30', 165;
    */
    

    Now, the query:

    ;WITH n(n) AS 
    (
      SELECT TOP 24 ROW_NUMBER() OVER (ORDER BY [object_id])
      FROM sys.objects
    ),
    x AS
    (
      SELECT 
        o.OutageDate, StartHour = (DATEPART(HOUR, StartTime) + n.n - 1) % 24,
        StartTime, EndTime, Duration,
        rn = ROW_NUMBER() OVER (PARTITION BY o.OutageDate, o.StartTime ORDER BY n.n)
      FROM n INNER JOIN dbo.Outages AS o
      ON n.n <= CEILING(DATEDIFF(MINUTE, CONVERT(DATETIME, StartTime), 
        DATEADD(DAY, CASE WHEN EndTime < StartTime THEN 1 ELSE 0 END, 
        CONVERT(DATETIME, EndTime)))/60.0)
     ),
     mx AS (SELECT OutageDate, StartTime, minrn = MIN(rn), maxrn = MAX(rn) 
       FROM x GROUP BY OutageDate, StartTime)
    
     -- insert into some other table
     SELECT 
        x.OutageDate, 
        x.StartHour, 
        StartMinutes = CASE 
          WHEN x.rn = mx.minrn THEN DATEPART(MINUTE, x.StartTime) ELSE 0 END,
        EndHour = x.StartHour + 1, 
        EndMinutes = CASE
          WHEN x.rn = mx.maxrn THEN DATEPART(MINUTE, x.EndTime) ELSE 0 END,
        x.StartTime, 
        x.EndTime,
        x.Duration
     FROM x INNER JOIN mx 
     ON x.OutageDate = mx.OutageDate
     AND x.StartTime = mx.StartTime
     ORDER BY x.OutageDate, x.rn;
    GO
    

    When you're happy that it is giving you the right rows for the various scenarios, then replace

    -- insert into some other table
    

    With an actual insert, e.g.

    INSERT dbo.OtherTable(col1, col2, ...)
    

    If you're trying to create a brand new table from this output, then replace

    FROM x INNER JOIN mx
    

    With an INTO clause, e.g.

    INTO dbo.MyNewTable FROM x INNER JOIN mx
    

    Don't forget to clean up:

    DROP TABLE dbo.Outages;
    
    0 讨论(0)
提交回复
热议问题