Найти разницу между двумя последовательными строками из результата в SQL Server 2008 - PullRequest
0 голосов
/ 24 мая 2019

Я хочу получить разницу в столбце «Данные» между двумя последовательными строками. Например, нужен Row2-Row1 (1902.4-1899.66), Row 3-Row 2 и так далее. Разница должна быть сохранена в новом столбце.

+----+-------+-----------+-------------------------+----+
| Name      | Data       |meter|       Time             |
+----+-------+-----------+-------------------------+----+
| Boiler-1  |  1899.66   | 1   | 5/16/2019 12:00:00 AM  |
| Boiler-1  |  1902.4    | 1   | 5/16/2019  12:15:00 AM |
| Boiler-1  |  1908.1    | 1   | 5/16/2019  12:15:00 AM |
| Boiler-1  |  1911.7    | 6   | 5/16/2019  12:15:00 AM |
| Boiler-1  |  1926.4    | 6   | 5/16/2019  12:15:00 AM |
| 
+----+-------+-----------+-------------------------     +

Дело в том, что структура таблицы, которую я показал в вопросе, фактически получена из двух разных таблиц. Я имею в виду, что приведенная выше таблица является результатом запроса Select для получения данных из двух разных таблиц. Идет как «выбрать имя, данные, unitId, метку времени из таблицы t1, присоединиться к таблице t2 .....». Так или иначе, я могу рассчитать разницу в значении столбца «data» между последовательными строками, не сохраняя показанный выше результат в стол?

Я использую SQL 2008, поэтому нельзя использовать функциональность Lead / Lag. Заранее спасибо за помощь.

Ответы [ 2 ]

1 голос
/ 24 мая 2019

Не утверждая, что это лучше, это просто еще одна опция в SQL SERVER <2012. Начиная с SQL Server 2012, легко сделать то же самое, добавив опцию LEAD и LAG по умолчанию. В любом случае, для малого и среднего набора данных, вы можете рассмотреть этот сценарий ниже:) </p>

Примечание: Это просто идея для вас.

WITH CTE(Name,Data)
AS
(
    SELECT 'Boiler-1' ,1899.66 UNION ALL
    SELECT 'Boiler-1',1902.4 UNION ALL
    SELECT 'Boiler-1',1908.1 UNION ALL
    SELECT 'Boiler-1',1911.7 UNION ALL
    SELECT 'Boiler-1',1926.4
    --Replace above select statement with your query
)
SELECT A.Name,A.Data,A.Data-ISNULL(B.Data,0) AS [Diff] 
FROM
(
    --Adding ROW_NUMBER Over (SELECT NULL) will keep the natural order
    --of your data and will just add the row number.
    SELECT *,ROW_NUMBER() OVER(ORDER BY (SELECT NULL))  RN  FROM CTE
)A
LEFT JOIN 
(
    SELECT *,ROW_NUMBER() OVER(ORDER BY (SELECT NULL))  RN FROM CTE
) B 
--Here the JOINING will take place on curent and next row for using ( = B.RN-1)
ON A.RN = B.RN-1
1 голос
/ 24 мая 2019

Эквивалент в SQL Server 2008 использует apply - и это может быть дорого:

with t as (
      <your query here>
     )
select t.*,
       (t.data - tprev.data) as diff
from t outer apply
     (select top (1) tprev.*
      from t tprev
      where tprev.name = t.name and
            tprev.boiler = t.boiler and
            tprev.time < t.time
      order by tprev.time desc
     ) tprev;

Предполагается, что вам нужна предыдущая строка, когда name и boiler совпадают. Вы можете изменить условие корреляции, если вы имеете в виду различные группировки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...