SQL сравнивает инкрементную разницу со столбцом - PullRequest
2 голосов
/ 09 ноября 2019

Допустим, у меня есть таблица со столбцами CurrentDateTime и CurrentValue, где столбец CurrentValue в основном увеличивается. Иногда, однако, CurrentValue сбрасывает, вот где начинаются проблемы.

Так что, если бы не было сброса время от времени, я мог бы просто сделать это:

SELECT MAX(CurrentValue)-MIN(CurrentValue) AS AccumulateValue 
FROM Table
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, CurrentDateTime), 0);

Если CurrentValue сбрасывается, AccumulateValue неверно.

Допустим, это значения, которые я получил:

CurrentDateTime    CurrentValue
-------------------------------
2019-10-01            100
2019-10-02            101
2019-10-03            102
2019-10-04            103
2019-10-05            104
2019-10-06            105

Это вернет 5

Но если значения выглядят следующим образом:

CurrentDateTime    CurrentValue
-------------------------------
2019-10-01            100
2019-10-02            101
2019-10-03            102
2019-10-04            103
2019-10-05            104
2019-10-06              0
2019-10-07              1
2019-10-08              2
2019-10-09              3

Результат будет 101, и он должен быть 7.

Я пробовал это (вычисление разницы между каждой строкой и запуск только SUMположительные значения):

SELECT SUM(CurrentValue)
FROM
    (SELECT 
         tb1.CurrentDateTime,
         CASE 
            WHEN tb1.CurrentValue > tb1.CurrentValueLag 
               THEN (tb1.CurrentValue - tb1.CurrentValueLag)
            WHEN tb1.CurrentValue <= tb1.CurrentValueLag
               THEN 0
         END AS CurrentValue
     FROM
         (SELECT 
              *,
              LAG(CurrentValue) OVER (ORDER BY CurrentDateTime ASC) AS CurrentValueLag 
          FROM Table) AS tb1) AS tb2
GROUP BY 
    DATEADD(MONTH, DATEDIFF(MONTH, 0, CurrentDateTime), 0);

Эта таблица довольно велика с небольшими приращениями, и SUM не верна по какой-то причине, которую я не могу понять. Я заметил, что при сравнении месяца (без сброса) значение из этого последнего запроса показывает более высокое значение, чем правильное значение.

Ответы [ 4 ]

0 голосов
/ 11 ноября 2019

Прежде всего. Спасибо за всю помощь, которую я получил.

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

В любом случае мне нужно было внести некоторые изменения в мой код, но вот оно:

SELECT YEAR(CurrentDateTime)
,MONTH(CurrentDateTime)
,SUM(tb2.CurrentValue) AS tb3.CurrentValue
 FROM(
     SELECT tb2.CurrentDateTime
    ,(tb2.CurrentValue - tb2.CurrentValue_LAG) AS CurrentValue --Only do math where there's not NULL.
     FROM(
         SELECT *
         , LAG(tb1.CurrentValue) OVER (ORDER BY tb1.CurrentDateTime ASC) AS 
         CurrentValue_LAG
         FROM(
             SELECT CurrentDateTime
             ,CASE WHEN CurrentValue = 0 THEN NULL ELSE CurrentValue END AS CurrentValue --NULLING the values to exclude them from the tb3 substract operation

             FROM TableOne
             WHERE CurrentDateTime BETWEEN '2019-01-01' AND '2019-12-31'
         ) AS tb1
     ) AS tb2
 ) AS tb3
GROUP BY YEAR(CurrentDateTime), MONTH(CurrentDateTime)

Может выглядеть грязно, но возвращает правильные значения.

0 голосов
/ 09 ноября 2019

Я думаю, что вы на правильном пути, используя lag(). Затем вы можете сделать кумулятивную сумму:

select
    sum(case when CurrentValue = CurrentValueLag + 1 then 1 else 0 end) result
from (
    select 
        t.*,
        lag(CurrentValue) over (order by CurrentDateTime) as CurrentValueLag
    from mytable t
) t
group by dateadd(month, datediff(month, 0, CurrentDateTime), 0);

Демонстрация на DB Fiddle :

Данные:

CurrentDateTime     | CurrentValue
:------------------ | -----------:
01/10/2019 00:00:00 |          100
02/10/2019 00:00:00 |          101
03/10/2019 00:00:00 |          102
04/10/2019 00:00:00 |          103
05/10/2019 00:00:00 |          104
06/10/2019 00:00:00 |            0
07/10/2019 00:00:00 |            1
08/10/2019 00:00:00 |            2
09/10/2019 00:00:00 |            3

Результаты:

| result |
| -----: |
|      7 |
0 голосов
/ 09 ноября 2019

Вы можете попробовать это.

DECLARE @TempTable TABLE (CurrentDateTime DATE,    CurrentValue INT)
INSERT INTO @TempTable VALUES

('2019-10-01', 100),
('2019-10-02', 101),
('2019-10-03', 102),
('2019-10-04', 103),
('2019-10-05', 104),
('2019-10-06',   0),
('2019-10-07',   1),
('2019-10-08',   2),
('2019-10-09',   3)

SELECT MAX(CurrentValue)-MIN(CurrentValue) AS AccumulateValue  FROM (
    SELECT CurrentDateTime, 
    CASE WHEN CurrentValue >= FIRST_VALUE(CurrentValue) OVER(PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, CurrentDateTime), 0) ORDER BY CurrentDateTime)
         THEN CurrentValue
         ELSE MAX(CurrentValue) OVER(PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, CurrentDateTime), 0)) + CurrentValue END AS CurrentValue
    FROM @TempTable
) T
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, CurrentDateTime), 0)

Результат:

AccumulateValue
---------------
7
0 голосов
/ 09 ноября 2019

Делаете ли вы простой WHERE фильтр, что хотите?

SELECT year(CurrentDateTime), month(currentDateTime),
       (MAX(CurrentValue) - MIN(CurrentValue)) AS AccumulateValue
FROM Table
WHERE CurrentValue > 0
GROUP BY year(CurrentDateTime), month(currentDateTime);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...