1

30 秒ごとに (timestamp, stock_price) を SQL データベースに記録するプログラムがあり、さまざまなタイムスケールでの株価のプロットを生成するとします。1 時間の範囲で測定値をプロットする場合、その間に取得した 120 個のサンプルすべてを使用してもかまいません。ただし、1 年間の範囲で価格をプロットしたい場合は、データベースから 100 万を超えるサンプルを取得したくないことは明らかです。サンプルの代表的なサブセットをデータベースから引き出す方がよいでしょう。

これは、コンピューター グラフィックスの詳細レベル テクニックを思い起こさせます。3D モデルから遠ざかるにつれて、忠実度の低いバージョンのモデルを使用できます。

データベースで詳細レベルの情報を表現したり、データの等間隔のサブセットをすばやくクエリしたりするための一般的な手法はありますか (たとえば、2009 年 1 月の等間隔のサンプルを 100 個ください)。


これまでに思いついた解決策は、データベース テーブルに level_of_detail 列を含めることです。level_of_detail=0 の場合、行は 1 つの瞬間的なサンプルを保持します。level_of_detail=n の場合、行には最後の (sample_interval*(2^n)) 秒のデータの平均が含まれ、このレベルには 1/(2^n) の行があります。テーブルには (level_of_detail, タイムスタンプ) のインデックスがあり、プロットを生成する場合は、必要なサンプル数に基づいて適切な level_of_detail 値を計算し、その制約でクエリを実行します。欠点は次のとおりです。

  • N 個のサンプルの場合、テーブルは 2*N 行を格納する必要があります
  • クライアントは、適切な level_of_detail 制約を指定することを知っている必要があります
  • サンプルがテーブルに追加されると、平均化された行を構築するプロセスが必要になります。
4

1 に答える 1

2

SQL Server の場合は、ntile. これにより、データセットが並べ替えられ、N 個の異なるグループに分割され、最初のグループには 1 が返され、最後のグループには N が返されます。

select  MIN(MeasureTime) as PeriodStart
,       MAX(MeasureTime) as PeriodEnd
,       AVG(StockPrice) as AvgStockPrice
from    (
        select  MeasureTime
        ,       StockPrice
        ,       NTILE(100) over (order by MeasureTime) as the_tile
        from    @t YourTable
        ) tiled
group by
        the_tile

これにより、正確に 100 行が返されます。クエリを試すことに興味がある場合は、テスト データのコピーを次に示します。

declare @t table (MeasureTime datetime, StockPrice int)
declare @dt date
set @dt = '2010-01-01'
while @dt < '2011-01-01'
    begin
    insert @t values (@dt, DATEDIFF(day,'2010-01-01',@dt))
    select @dt = DATEADD(day,1,@dt)
    end
于 2011-01-20T18:40:18.347 に答える