2

タイムラインの各日付について、いくつかのメジャーとそれらが測定された日付を含むデータ セット内の最新の N データ ポイントの移動平均を示すタイムライン レポートを作成したいと考えています。日付を提供するために、毎日データが入力されたカレンダー テーブルがあります。相関サブクエリを使用して、その日付より前の全体的な平均を示すタイムラインをかなり簡単に計算できます (実際の状況はこれよりもはるかに複雑ですが、本質的には次のように単純化できます)。

SELECT  c.date
,       (   SELECT  AVERAGE(m.value) 
            FROM    measures as m
            WHERE   m.measured_on_dt <= c.date
        ) as `average_to_date`
FROM    calendar c
WHERE   c.date between date1 AND date2  -- graph boundaries
ORDER BY c.date ASC

私はこれを読んで何日も過ごしましたが、良い解決策は見つかりませんでした。サブクエリで LIMIT が機能する可能性があると示唆する人もいますが (LIMIT は現在のバージョンの MySQL のサブクエリでサポートされています)、LIMIT は集計に入る行ではなく、戻りセットに適用されるため、追加しても違いはありません。

また、集約されていない SELECT を LIMIT で記述してから集約することもできません。これは、相関サブクエリが FROM ステートメント内で許可されていないためです。したがって、これは(悲しいことに)機能しません:

SELECT  c.date
,       SELECT AVERAGE(last_5.value)
        FROM (  SELECT  m.value
                FROM    measures as m
                WHERE   m.measured_on_dt <= c.date
                ORDER BY m.measured_on_dt DESC
                LIMIT 5
              ) as `last_5`
FROM    calendar c
WHERE   c.date between date1 AND date2  -- graph boundaries
ORDER BY c.date ASC

サブクエリアプローチを完全に回避し、ユーザー変数を使用した巧妙な結合/行番号付け手法でこれを行うかどうかを確認し、それを集計する必要があると考えていますが、それに取り組んでいる間、誰かに尋ねると思いましたより良い方法を知っていましたか?

更新: さて、この例のために単純化したソリューションが機能しています。カレンダーの日付から逆方向にメジャーに番号を付けるために、ユーザー変数のトリックに依存しています。また、(サブクエリの代わりに) カレンダー テーブルとの外積も行いますが、これには、行番号付けのトリックが失敗するという不幸な副作用があります (ユーザー変数は、クライアントに送信されるときではなく、クライアントに送信されるときに評価されます)。行が評価されます) したがって、これを回避するには、クエリを 1 レベル入れ子にし、結果を並べ替えてから、そのセットに行番号付けのトリックを適用する必要がありました。

このクエリは、メジャーがあるカレンダーの日付のみを返すため、タイムライン全体が必要な場合は、カレンダーを選択して、この結果セットに LEFT JOIN するだけです。

set @day = 0;
set @num = 0;
set @LIMIT = 5;

SELECT  date
,       AVG(value) as recent_N_AVG
FROM
(  SELECT *
  ,      @num := if(@day = c.date, @num + 1, 1) as day_row_number
  ,      @day := day as dummy
  FROM 
  ( SELECT  c.full_date
    ,       m.value
    ,       m.measured_on_dt
    FROM    calendar c 
    JOIN    measures as m
    WHERE   m.measured_on_dt <= c.full_date
    AND     c.full_date BETWEEN date1 AND date2  
    ORDER BY c.full_date ASC, measured_on_dt DESC
  ) as full_data
) as numbered
WHERE day_row_number <= @LIMIT
GROUP BY date

行番号付けのトリックは、より複雑なデータに一般化できます (私の測定値は、集計が必要ないくつかの次元にあります)。

4

1 に答える 1

0

タイムラインが連続している場合 (毎日 1 つの値)、次のように最初の試行を改善できます。

SELECT c.date,
       ( SELECT AVERAGE(m.value) 
         FROM   measures as m
         WHERE  m.measured_on_dt 
                    BETWEEN DATE_SUB(c.date, INTERVAL 5 day) AND c.date
       ) as `average_to_date`
FROM    calendar c
WHERE   c.date between date1 AND date2  -- graph boundaries
ORDER BY c.date ASC

タイムラインに穴がある場合、平均の値が 5 つ未満になります。

于 2012-04-12T11:22:05.330 に答える