2013-02-25 3 views
0

Мой главный запрос был решен на следующей постРазница между каждым значением строки - Сумма Ошибка

TSQL - Get the difference between each row value

У меня есть одна проблема суммированием значений чтения между каждой строки.

id device_id time reading shift_id 
150323 3 2013-02-25 15:22:01.273 999948.00 43 
150324 1 2013-02-25 15:22:01.423 999962.00 43 
150325 3 2013-02-25 15:22:01.463 999966.00 43 
150326 1 2013-02-25 15:22:01.610 999979.00 43 
150327 3 2013-02-25 15:22:01.650 999983.00 43 
150328 1 2013-02-25 15:22:01.810 999997.00 43 

для приведенного выше сценария я получаю результаты, но при следующем в случае показания поступают правильно в соответствии с решением, предоставленной мне, но я хочу, чтобы увеличить разницу ...

id device_id time reading shift_id 
150322 1 2013-02-25 15:22:01.233 999945.00 43 
150323 3 2013-02-25 15:22:01.273 999948.00 43 
150324 1 2013-02-25 15:22:01.423 999962.00 43 
150325 3 2013-02-25 15:22:01.463 999966.00 43 
150326 1 2013-02-25 15:22:01.610 999979.00 43 
150327 3 2013-02-25 15:22:01.650 999983.00 43 
150328 1 2013-02-25 15:22:01.810 999997.00 43 
150329 3 2013-02-25 15:22:01.853 1.00 43 
150330 1 2013-02-25 15:22:02.000 15.00 43 
150331 3 2013-02-25 15:22:02.040 18.00 43 
150332 1 2013-02-25 15:22:02.187 32.00 43 

в результате указанных выше показаний, как показано ниже

Day Shifts Hour Device ID Count1 
2013-02-25 2nd 11 1 39145.00 
2013-02-25 2nd 11 3 39148.00 
2013-02-25 2nd 12 1 248022.00 
2013-02-25 2nd 12 3 248022.00 
2013-02-25 2nd 13 1 389195.00 
2013-02-25 2nd 13 3 389197.00 
2013-02-25 2nd 14 1 201855.00 
2013-02-25 2nd 14 3 201854.00 
2013-02-25 2nd 15 1 -877108.00 
2013-02-25 2nd 15 3 -877112.00 

Эти два значения в отрицательном должны быть в положительной, и значение должно быть что-то вроде 122892 - 122889.

Примечание: Максимальное значение для чтения всегда будет 999999,00, после чего я снова начну с 0 до 999999,00 и снова начну с 0. Это в основном счетное устройство, которое рассчитывается. Ниже приведен запрос, который был предложен на переполнение стека и я модифицировал немного по моей потребности

declare @fromdate datetime; 
declare @todate datetime; 
declare @total as decimal(18,2); 
SET @fromdate = '2/23/2013 10:51:17 AM'; 
SET @todate ='2/25/2013 12:10:56 PM'; 
WITH cte AS 
( 
    SELECT *, 
      ROW_NUMBER() OVER(PARTITION BY device_id ORDER BY [time]) AS NId 
    FROM [dbo].[readings] r 
    where  cast(r.time as date)>= CAST(@fromdate as date) and 
      cast(r.time as date) <= CAST(@todate as date) and 
      r.device_id<>5 
) 
SELECT CAST (c1.[time] as DATE) as [Day], 
       (
        select s.name from shifts s where s.id = c1.shift_id 
       ) as Shifts, 
       DATEPART(hour,c1.time) as [Hour], 
       c1.device_id as [Device ID], 
       (select 
        case when sum(c2.reading - ISNULL(c1.reading, c2.reading)) < 0 then 
         sum(c1.reading - ISNULL(c2.reading, c1.reading))     
        else 
         sum(c2.reading - ISNULL(c1.reading, c2.reading)) 

        end 
       ) AS Count1 
       FROM  cte c1 left JOIN cte c2 ON c1.device_id = c2.device_id AND 
         c1.NId + 1 = c2.NId 
    group by cast(c1.time as DATE), c1.shift_id , DATEPART(hour,c1.time), c1.device_id 
    order by cast(c1.time as DATE), c1.shift_id,DATEPART(hour,c1.time), c1.device_id 

ответ

1

Что вы, по сути нужно сделать вид, что временно c2.reading не обтекать после достижения 1.000.000, и только когда c2.reading < c1.reading. То есть в этот момент вам нужно увеличить c2.reading на 1,000,000, а затем вычесть c1.reading. И когда c2.reading >= c1.reading, запрос должен рассчитать «нормальную» разницу, то есть вычесть c1.reading из исходного (не увеличенного) значения c2.reading.

Одним из способов достижения этой логики было бы сделать что-то так просто, как это:

SUM(
    CASE WHEN c2.reading < c1.reading THEN 1000000 ELSE 0 END 
    + c2.reading 
    - ISNULL(c1.reading, c2.reading) 
) AS Count1 

Однако есть и другой подход.

Ваши значения чтения и, как следствие, различия между любыми двумя из них также не могут превышать 1 000 000. Таким образом, вы можете свободно применять modulo 1,000,000 к положительной разницы и это даст вам ту же разницу обратно:

d mod 1,000,000 = d 

Кроме того, добавление кратные 1,000,000 к положительной разницы не будет влиять на результат по модулю 1000000, потому что , в соответствии с distributiveness операции по модулю,

(d + 1,000,000 * n) mod 1,000,000 = 
= d mod 1,000,000 + (1,000,000 * n) mod 1,000,000 

первое слагаемое, d mod 1,000,000 приводит к d, второй, (1,000,000 * n) mod 1,000,000 дает 0, d + 0 = d.

С другой стороны, добавление 1 000 000 к отрицательным значениям даст нам правильную положительную разницу.

Таким образом, чтобы подвести итог,

  • добавляя 1000000 к отрицательной разнице дает нам (правильную) положительную разницу,

  • положительная разница по модулю 1000000 дает то же положительное значение, и

  • добавление 1 000 000 к положительной разнице не влияет на результат по модулю 1 000 000.

Принимая все это во внимание, мы можем в конечном итоге со следующим универсальным выражением для вычисления одного различия:

(1000000 + c2.reading - ISNULL(c1.reading, c2.reading)) % 1000000 

где % оператор по модулю in Transact-SQL.

Поместите выражение в SUM получить соответствующие агрегированные значения:

SUM((c2.reading + 1000000 - ISNULL(c1.reading, c2.reading)) % 1000000) AS Count1 
+0

Эй Андрей, ваша магия работала. Спасибо за помощь. –

Смежные вопросы