使用增量值更新组

Updating a group by with incrementing values

我在 SQL Server 2016 中有一个 table,如下所示:

ID  DataDate    DataHour Value  UpdateDate  UpdateTime
23  09/03/2019   11       65.2  09/15/2019   04:15:209
16  09/03/2019   11       66.7  09/15/2019   04:15:209
26  09/03/2019   11       62.3  09/15/2019   04:15:209
27  09/03/2019   11       69.8  09/15/2019   04:15:209
15  09/03/2019   11       59.2  09/15/2019   04:15:209
22  09/02/2019   11       45.2  09/15/2019   04:15:209
41  09/02/2019   11       36.7  09/15/2019   04:15:209
25  09/02/2019   11       62.3  09/15/2019   04:15:209
21  09/02/2019   11       79.8  09/15/2019   04:15:209
12  09/02/2019   11       19.2  09/15/2019   04:15:209
17  09/02/2019   11       19.2  09/15/2019   04:15:209

我想更新 UpdateDate 和 UpdateTime 列,如下所示: - 按 DataDate、DataHour 分组 - 按 ID Desc 排序(例如,最高优先) - 保持组的第一行不变 - 对于组中剩余的每一行,从 UpdateTime 中减去一小时 - 如果更新的 UpdateTime 转到前一天(即小时 = 23),则将 UpdateDate 减少 1 天

结果应如下所示:

ID  DataDate    DataHour Value  UpdateDate  UpdateTime
23  09/03/2019   11       65.2  09/15/2019   02:15:209
16  09/03/2019   11       66.7  09/15/2019   01:15:209
26  09/03/2019   11       62.3  09/15/2019   03:15:209
27  09/03/2019   11       69.8  09/15/2019   04:15:209
15  09/03/2019   11       59.2  09/15/2019   00:15:209
22  09/02/2019   11       45.2  09/15/2019   02:15:209
41  09/02/2019   11       36.7  09/15/2019   04:15:209
25  09/02/2019   11       62.3  09/15/2019   03:15:209
21  09/02/2019   11       79.8  09/15/2019   01:15:209
12  09/02/2019   11       19.2  09/14/2019   23:15:209
17  09/02/2019   11       19.2  09/15/2019   00:15:209

这是我目前的情况:

UPDATE t
SET t.UpdateTime = DATEADD(hour,-1,g.UpdateTime), t.UpdateDate = CASE WHEN DATEPART(hour,DATEADD(hour,-1,g.UpdateTime)) = 23 THEN DATEADD(day,-1,g.UpdateDate) ELSE g.UpdateDate END
FROM mytable t
INNER JOIN (
    SELECT MAX(ID) As ID, DataDate, DataHour, MAX(UpdateDate) As UpdateDate, MAX(UpdateTime) As UpdateTime
    FROM mytable
    GROUP BY DataDate, DataHour, ID
    ORDER BY DataDate, DataHour, ID DESC
) g
ON g.id = t.id

但这并没有正确地在整个组中递增。不确定我是否需要 window 函数来帮助解决这个问题。

将日期和时间值分开会使这变得困难(时间格式错误也是如此),但这应该可以满足您的要求。

首先,创建测试数据:

CREATE TABLE #tmp (ID int, DataDate date, DataHour int, Value decimal(9,1), UpdateDate date, UpdateTime Time(3))
INSERT INTO #tmp Values
    (23,'09/03/2019', 11, 65.2,'09/15/2019', '04:15:20.9'),
    (16  ,'09/03/2019',   11       ,66.7  ,'09/15/2019', '04:15:20.9'),
    (26  ,'09/03/2019',   11       ,62.3  ,'09/15/2019', '04:15:20.9'),
    (27  ,'09/03/2019',   11       ,69.8  ,'09/15/2019', '04:15:20.9'),
    (15  ,'09/03/2019',   11       ,59.2  ,'09/15/2019', '04:15:20.9'),
    (22  ,'09/02/2019',   11       ,45.2  ,'09/15/2019', '04:15:20.9'),
    (41  ,'09/02/2019',   11       ,36.7  ,'09/15/2019', '04:15:20.9'),
    (25  ,'09/02/2019',   11       ,62.3  ,'09/15/2019', '04:15:20.9'),
    (21  ,'09/02/2019',   11       ,79.8  ,'09/15/2019', '04:15:20.9'),
    (12  ,'09/02/2019',   11       ,19.2  ,'09/15/2019', '04:15:20.9'),
    (17  ,'09/02/2019',   11       ,19.2  ,'09/15/2019', '04:15:20.9')

下面是将生成所需输出的代码。修改它并根据需要将其放入 UPDATE 语句中:

;WITH Base as (
    SELECT 
        DataDate, 
        DataHour,
        Max(UpdateDate) as BaseDate,
        Max(UpdateTime) as BaseTime
    FROM #tmp t2
    GROUP BY DataDate, 
        DataHour
),
AdjData as (
    SELECT 
        ID,
        t.DataDate,
        t.DataHour,
        t.Value,
        Cast(BaseDate as Datetime) + Cast(BaseTime as DateTime) as BaseDateTime
        ,row_number() over (Partition by t.DataDate, t.DataHour ORDER BY t.Id Desc) as Adj
    FROM #tmp t
    INNER JOIN Base b
        ON t.DataDate = b.DataDate
        AND t.DataHour = b.DataHour
    )
SELECT Id,
    DataDate,
    DataHour,
    Value,
    Cast(Dateadd(hour, -(Adj-1), BaseDateTime) AS date) as UpdateDate,
    Cast(Dateadd(hour, -(Adj-1), BaseDateTime) AS Time(3)) as UpdateTime
FROM AdjData