3

変更された場合にのみDerbyデータベースにデータを挿入するアプリケーション用の新しいデータ ソースを受け取りました。通常、欠落しているデータは問題ありません。データ (時間の経過に伴う値) を使用して折れ線グラフを描いています。2 つの点の間に線を引いて、任意の点での期待値を外挿します。問題は、この場合の欠落データは「直線を引く」ことを意味するため、これを行うとグラフが正しくないことです。

これを修正するには 2 つの方法があります。欠落しているデータを別の方法で処理する新しいクラスを作成する方法 (prefuse、使用している描画ライブラリが描画を処理する方法が原因で難しい場合があります)、または行を複製する方法です。各行のx値を変更しながら、y値を同じままにします。データベースとレンダラーを橋渡しする Java でこれを行うことも、SQL を変更することもできます。

私の質問は、以下のような結果セットが与えられた場合です:

+-------+---------------------+
| value | received            |
+-------+---------------------+
|     7 | 2000-01-01 08:00:00 |
|    10 | 2000-01-01 08:00:05 |
|    11 | 2000-01-01 08:00:07 |
|     2 | 2000-01-01 08:00:13 |
|     4 | 2000-01-01 08:00:16 |
+-------+---------------------+

8:00:20 にクエリを実行すると仮定すると、SQL を使用して次のようにするにはどうすればよいでしょうか? 基本的に、すでに取得されるまで、毎秒行を複製しています。receivedすべての意図と目的のために、一意です(そうではありませんがWHERE、クエリの句が原因です)。

+-------+---------------------+
| value | received            |
+-------+---------------------+
|     7 | 2000-01-01 08:00:00 |
|     7 | 2000-01-01 08:00:01 |
|     7 | 2000-01-01 08:00:02 |
|     7 | 2000-01-01 08:00:03 |
|     7 | 2000-01-01 08:00:04 |
|    10 | 2000-01-01 08:00:05 |
|    10 | 2000-01-01 08:00:06 |
|    11 | 2000-01-01 08:00:07 |
|    11 | 2000-01-01 08:00:08 |
|    11 | 2000-01-01 08:00:09 |
|    11 | 2000-01-01 08:00:10 |
|    11 | 2000-01-01 08:00:11 |
|    11 | 2000-01-01 08:00:12 |
|     2 | 2000-01-01 08:00:13 |
|     2 | 2000-01-01 08:00:14 |
|     2 | 2000-01-01 08:00:15 |
|     4 | 2000-01-01 08:00:16 |
|     4 | 2000-01-01 08:00:17 |
|     4 | 2000-01-01 08:00:18 |
|     4 | 2000-01-01 08:00:19 |
|     4 | 2000-01-01 08:00:20 |
+-------+---------------------+

ご協力いただきありがとうございます。

4

9 に答える 9

3

SQL のセットベースの性質により、これを行う簡単な方法はありません。私は 2 つのソリューション戦略を使用しました。

a)サイクルを使用して最初から終了日時まで移動し、各ステップで値を取得し、それを一時テーブルに挿入します

b) 1 分刻みでテーブル (通常または一時) を生成し、このテーブルに基本日時を追加して、ステップを生成できます。

アプローチの例 b) (SQL Server 版)

24 時間以上のデータをクエリすることは決してないと仮定しましょう。各ステップの分数を含む dttm フィールドを持つ表の間隔を作成します。そのテーブルは事前に設定されている必要があります。

select dateadd(minute,stepMinutes,'2000-01-01 08:00') received,
(select top 1 value from table where received <= 
dateadd(minute,dttm,'2000-01-01 08:00') 
order by received desc) value
from intervals
于 2009-06-15T19:27:47.247 に答える
2

この場合、これらすべてのデータポイントを生成する必要はないようです。代わりに以下を生成するのは正しいでしょうか? 直線を描いている場合は、1 秒ごとにデータ ポイントを生成する必要はありません。データ ポイントごとに 2 つだけです...現在の時刻に 1 つ、次の時刻の直前に 1 つです。この例では、次回から 5 ミリ秒減算しますが、必要に応じて 1 秒にすることもできます。

+-------+---------------------+
| value | received            |
+-------+---------------------+
|     7 | 2000-01-01 08:00:00 |
|     7 | 2000-01-01 08:00:04 |
|    10 | 2000-01-01 08:00:05 |
|    10 | 2000-01-01 08:00:06 |
|    11 | 2000-01-01 08:00:07 |
|    11 | 2000-01-01 08:00:12 |
|     2 | 2000-01-01 08:00:13 |
|     2 | 2000-01-01 08:00:15 |
|     4 | 2000-01-01 08:00:16 |
|     4 | 2000-01-01 08:00:20D |
+-------+---------------------+

その場合は、次のことができます。

SELECT * FROM
(SELECT * from TimeTable as t1
UNION
SELECT t2.value, dateadd(ms, -5, t2.received)
from ( Select t3.value, (select top 1 t4.received  
                         from TimeTable t4 
                         where t4.received > t3.received
                         order by t4.received asc) as received
from TimeTable t3) as t2
UNION
SELECT top 1 t6.value, GETDATE()
from TimeTable t6
order by t6.received desc
) as t5
where received IS NOT NULL
order by t5.received

これの大きな利点は、セットベースのソリューションであり、反復的なアプローチよりもはるかに高速であることです。

于 2009-06-15T19:59:42.253 に答える
1

カーソルを移動し、返された最後の値と時間の変数を保持し、現在の値が1秒以上進んでいる場合は、現在の行を取得するまで、前の値と新しい時間を使用して一度に1秒ループします時間。

SQL でこれを行うのは大変です。欠落しているデータを作成した場合は、実際のデータ ポイントまたは補間されたデータ ポイントを追跡するために列を追加する必要があります。

于 2009-06-15T20:06:32.597 に答える
0

単なるアイデアとして、Anthony MollinaroのSQLクックブックの第9章を確認することをお勧めします。彼には、主に何をしようとしているのかを説明するレシピ「Filling in MissingDates」 (278〜281ページを確認)があります。ヘルパーテーブルを介するか、クエリを再帰的に実行するかのいずれかで、ある種の順次処理が必要です。彼はDerbyの例を直接持っていませんが、おそらくそれらを問​​題に適応させることができると思います(特に、PostgreSQLまたはMySQLの場合、プラットフォームに依存しないようです)。

于 2009-06-15T21:09:34.963 に答える
0

セットベースの性質があるため、SQL/データベースでこれを解決することはお勧めしません。また、ここでは秒を扱っているので、データベースからアプリケーションに転送する必要がある、同じ繰り返しデータを含む多くの行が作成される可能性があると思います。

于 2009-06-15T19:40:15.223 に答える
0

これを処理する 1 つの方法は、受信したすべての値を含むテーブルに対してデータを左結合することです。次に、その行に値がない場合は、前と次の実際の値に基づいて予測値を計算します。

使用しているデータベース プラットフォームについては言及していません。SQL Server では、開始日時と終了日時の値を受け入れるユーザー定義関数を作成します。必要なすべての受信値を含むテーブル値が返されます。

以下でシミュレートしました。これは SQL Server で実行されます。rにエイリアスされた副選択は、ユーザー定義関数によって実際に返されるものです。

select r.received,
isnull(d.value,(select top 1 data.value from data where data.received < r.received order by data.received desc)) as x
from (
    select cast('2000-01-01 08:00:00' as datetime) received
    union all
    select cast('2000-01-01 08:00:01' as datetime)
    union all
    select cast('2000-01-01 08:00:02' as datetime)
    union all
    select cast('2000-01-01 08:00:03' as datetime)
    union all
    select cast('2000-01-01 08:00:04' as datetime)
    union all
    select cast('2000-01-01 08:00:05' as datetime)
    union all
    select cast('2000-01-01 08:00:06' as datetime)
    union all
    select cast('2000-01-01 08:00:07' as datetime)
    union all
    select cast('2000-01-01 08:00:08' as datetime)
    union all
    select cast('2000-01-01 08:00:09' as datetime)
    union all
    select cast('2000-01-01 08:00:10' as datetime)
    union all
    select cast('2000-01-01 08:00:11' as datetime)
    union all
    select cast('2000-01-01 08:00:12' as datetime)
    union all
    select cast('2000-01-01 08:00:13' as datetime)
    union all
    select cast('2000-01-01 08:00:14' as datetime)
    union all
    select cast('2000-01-01 08:00:15' as datetime)
    union all
    select cast('2000-01-01 08:00:16' as datetime)
    union all
    select cast('2000-01-01 08:00:17' as datetime)
    union all
    select cast('2000-01-01 08:00:18' as datetime)
    union all
    select cast('2000-01-01 08:00:19' as datetime)
    union all
    select cast('2000-01-01 08:00:20' as datetime)
) r
left outer join Data d on r.received = d.received
于 2009-06-15T19:22:58.037 に答える
0

グラフに表示する軸の値ごとにテーブルを作成し、それに結合するか、そこにデータ フィールドを配置して、値が到着したときにそのレコードを更新することをお勧めします。

「欠損値」の問題は非常に広範囲に及ぶため、しっかりとしたポリシーを持つことをお勧めします。

発生することの 1 つは、値が欠落している複数の隣接するスロットが存在することです。

これを OLAP データに変換できれば、はるかに簡単になります。

于 2009-06-15T19:28:07.167 に答える
0

SQL Server を使用している場合は、これが適切な出発点になります。Apache の Derby が sql にどれほど近いかはわかりません。

Usage: EXEC ElaboratedData '2000-01-01 08:00:00','2000-01-01 08:00:20'

CREATE PROCEDURE [dbo].[ElaboratedData]
  @StartDate DATETIME,
  @EndDate DATETIME
AS
  --if not a valid interval, just quit
  IF @EndDate<=@StartDate BEGIN
    SELECT 0;    
    RETURN;
  END;

  /*
  Store the value of 1 second locally, for readability
  --*/
  DECLARE @OneSecond FLOAT;
  SET @OneSecond = (1.00000000/86400.00000000);

  /*
  create a temp table w/the same structure as the real table.
  --*/
  CREATE TABLE #SecondIntervals(TSTAMP DATETIME, DATAPT INT);

  /*
  For each second in the interval, check to see if we have a known value.
  If we do, then use that.  If not, make one up.
  --*/ 
  DECLARE @CurrentSecond DATETIME; 
  SET @CurrentSecond = @StartDate;
  WHILE @CurrentSecond <= @EndDate BEGIN
    DECLARE @KnownValue INT;

    SELECT @KnownValue=DATAPT
    FROM TESTME
    WHERE TSTAMP = @CurrentSecond;

    IF (0 = ISNULL(@KnownValue,0)) BEGIN
      --ok, we have to make up a fake value
      DECLARE @MadeUpValue INT;
      /*
      *******Put whatever logic you want to make up a fake value here
      --*/
      SET @MadeUpValue = 99;

      INSERT INTO #SecondIntervals(
        TSTAMP
       ,DATAPT
      )
      VALUES(
        @CurrentSecond
       ,@MadeUpValue
      );
    END;  --if we had to make up a value
    SET @CurrentSecond = @CurrentSecond + @OneSecond;
  END;  --while looking thru our values

  --finally, return our generated values + real values
  SELECT TSTAMP, DATAPT FROM #SecondIntervals
  UNION ALL
  SELECT TSTAMP, DATAPT FROM TESTME
  ORDER BY TSTAMP;
GO
于 2009-06-15T20:46:13.273 に答える
0

すべての分を含む単純なテーブルを作成します (警告、しばらく実行されます)。

Create Table Minutes(Value DateTime Not Null)
Go

Declare @D DateTime
Set @D = '1/1/2000'

While (Year(@D) < 2002)
Begin
  Insert Into Minutes(Value) Values(@D)
  Set @D = DateAdd(Minute, 1, @D)
End
Go


Create Clustered Index IX_Minutes On Minutes(Value)
Go

その後、次のように使用できます。

Select 
  Received = Minutes.Value,
  Value = (Select Top 1 Data.Value
           From Data
           Where Data.Received <= Minutes.Received
           Order By Data.Received Desc)
From
  Minutes
Where
  Minutes.Value Between @Start And @End
于 2009-06-15T19:29:17.227 に答える