タイムラインの各日付について、いくつかのメジャーとそれらが測定された日付を含むデータ セット内の最新の 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
行番号付けのトリックは、より複雑なデータに一般化できます (私の測定値は、集計が必要ないくつかの次元にあります)。