0

私の主な質問は次の投稿で解決されました

TSQL - 各行の値の差を取得する

各行間の読み取り値を合計するという問題が 1 つあります。

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

負のこれら 2 つの値は正である必要があり、値は 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
4

1 に答える 1

1

本質的に必要なのは、c2.reading1,000,000 に達した後、一時的にラップアラウンドしなかったふりをすることc2.reading < c1.readingです。つまり、その時点でc2.reading1,000,000 増やしてから を引く必要がありますc1.reading。の場合c2.reading >= c1.reading、クエリは「通常の」差を計算する必要があります。つまりc1.reading、元の (増加していない)c2.reading値から減算します。

そのロジックを実現する 1 つの方法は、次のように単純なことを行うことです。

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

ただし、別のアプローチもあります。

あなたの読書値、そして結果として、それらのうちの任意の 2 つの値の差も、1,000,000 を超えることはできません。したがって、モジュロ1,000,000 を正の差に自由に適用すると、同じ差が返されます。

d mod 1,000,000 = d

さらに、正の差に 1,000,000 の倍数を追加しても、1,000,000 を法とする結果には影響しません。これは、法演算の分配性によると、

  (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、2 番目の被加数(1,000,000 * n) mod 1,000,000は 0 になりd + 0 = dます。

一方、の差に 1,000,000 を追加すると、正しい正の差が得られます。

つまり、要約すると、

  • 負の差に 1,000,000 を追加すると、(正しい) 正の差が得られます。

  • 1,000,000 を法とする正の差は、同じ正の差をもたらします。

  • 正の差に 1,000,000 を追加しても、モジュロ 1,000,000 の結果には影響しません。

これらすべてを考慮に入れると、単一の差を計算するための次の普遍的な式にたどり着くことができます。

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

whereはTransact-SQL%のモジュロ演算子です。

式を入れてSUM、対応する集計値を取得します。

SUM((c2.reading + 1000000 - ISNULL(c1.reading, c2.reading)) % 1000000) AS Count1
于 2013-02-25T15:31:37.357 に答える