Обновление группы путем увеличения значений - PullRequest
0 голосов
/ 24 сентября 2019

У меня есть таблица в SQL Server 2016, которая выглядит следующим образом:

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 - Упорядочить по идентификатору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

Но это не увеличивается по группе должным образом.Не уверен, что мне нужна оконная функция, чтобы помочь с этим.

1 Ответ

1 голос
/ 25 сентября 2019

Разделение значений даты и времени делает это трудным (как и тот факт, что время было отформатировано), но это должно делать то, что вы хотите.

Сначала создайте тестовые данные:

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
...