この回答は、ティッカーから高値/安値/始値/終値を生成する方法を示しています。
任意の時間間隔で集計を取得
これに基づいてソリューションを実装しようとしていますが(PG 9.2)、first_value()
の正しい値を取得するのが困難です。
これまでに、2つのクエリを試しました。
_SELECT
cstamp,
price,
date_trunc('hour',cstamp) AS h,
floor(EXTRACT(minute FROM cstamp) / 5) AS m5,
min(price) OVER w,
max(price) OVER w,
first_value(price) OVER w,
last_value(price) OVER w
FROM trades
Where date_trunc('hour',cstamp) = timestamp '2013-03-29 09:00:00'
WINDOW w AS (
PARTITION BY date_trunc('hour',cstamp), floor(extract(minute FROM cstamp) / 5)
ORDER BY date_trunc('hour',cstamp) ASC, floor(extract(minute FROM cstamp) / 5) ASC
)
ORDER BY cstamp;
_
これが結果の一部です。
_ cstamp price h m5 min max first last
"2013-03-29 09:19:14";77.00000;"2013-03-29 09:00:00";3;77.00000;77.00000;77.00000;77.00000
"2013-03-29 09:26:18";77.00000;"2013-03-29 09:00:00";5;77.00000;77.80000;77.80000;77.00000
"2013-03-29 09:29:41";77.80000;"2013-03-29 09:00:00";5;77.00000;77.80000;77.80000;77.00000
"2013-03-29 09:29:51";77.00000;"2013-03-29 09:00:00";5;77.00000;77.80000;77.80000;77.00000
"2013-03-29 09:30:04";77.00000;"2013-03-29 09:00:00";6;73.99004;77.80000;73.99004;73.99004
_
ご覧のとおり、77.8はではありませんfirst_value()
の正しい値であると私が信じている値は77.0です。
これはWINDOW
の_ORDER BY
_があいまいなためかもしれませんが、これを
_ORDER BY cstamp ASC
_
しかし、これはPARTITION
も混乱させるようです:
_ cstamp price h m5 min max first last
"2013-03-29 09:19:14";77.00000;"2013-03-29 09:00:00";3;77.00000;77.00000;77.00000;77.00000
"2013-03-29 09:26:18";77.00000;"2013-03-29 09:00:00";5;77.00000;77.00000;77.00000;77.00000
"2013-03-29 09:29:41";77.80000;"2013-03-29 09:00:00";5;77.00000;77.80000;77.00000;77.80000
"2013-03-29 09:29:51";77.00000;"2013-03-29 09:00:00";5;77.00000;77.80000;77.00000;77.00000
"2013-03-29 09:30:04";77.00000;"2013-03-29 09:00:00";6;77.00000;77.00000;77.00000;77.00000
_
maxとlast nowの値はパーティション内で変化するため。
何が悪いのですか? PARTITION
内のORDER
とWINDOW
の関係を理解するのを手伝ってくれませんか?
答えはありますが、誰でもテーブルを再作成できるように、トリミングされたpg_dumpを以下に示します。唯一異なるのは、テーブル名です。
_CREATE TABLE wtest (
cstamp timestamp without time zone,
price numeric(10,5)
);
COPY wtest (cstamp, price) FROM stdin;
2013-03-29 09:04:54 77.80000
2013-03-29 09:04:50 76.98000
2013-03-29 09:29:51 77.00000
2013-03-29 09:29:41 77.80000
2013-03-29 09:26:18 77.00000
2013-03-29 09:19:14 77.00000
2013-03-29 09:19:10 77.00000
2013-03-29 09:33:50 76.00000
2013-03-29 09:33:46 76.10000
2013-03-29 09:33:15 77.79000
2013-03-29 09:30:08 77.80000
2013-03-29 09:30:04 77.00000
\.
_
使用したすべての関数は、パーティションではなくウィンドウフレームで機能します。省略した場合、フレームの終わりが現在の行になります。ウィンドウフレームをパーティション全体にするには、フレーム句(range...
)で宣言します。
SELECT
cstamp,
price,
date_trunc('hour',cstamp) AS h,
floor(EXTRACT(minute FROM cstamp) / 5) AS m5,
min(price) OVER w,
max(price) OVER w,
first_value(price) OVER w,
last_value(price) OVER w
FROM trades
Where date_trunc('hour',cstamp) = timestamp '2013-03-29 09:00:00'
WINDOW w AS (
PARTITION BY date_trunc('hour',cstamp) , floor(extract(minute FROM cstamp) / 5)
ORDER BY cstamp
range between unbounded preceding and unbounded following
)
ORDER BY cstamp;
次に、動作を説明する簡単なクエリを示します。
_select
v,
first_value(v) over w1 f1,
first_value(v) over w2 f2,
first_value(v) over w3 f3,
last_value (v) over w1 l1,
last_value (v) over w2 l2,
last_value (v) over w3 l3,
max (v) over w1 m1,
max (v) over w2 m2,
max (v) over w3 m3,
max (v) over () m4
from (values(1),(2),(3),(4)) t(v)
window
w1 as (order by v),
w2 as (order by v rows between unbounded preceding and current row),
w3 as (order by v rows between unbounded preceding and unbounded following)
_
上記のクエリの出力は次のとおりです( SQLFiddle here ):
_| V | F1 | F2 | F3 | L1 | L2 | L3 | M1 | M2 | M3 | M4 |
|---|----|----|----|----|----|----|----|----|----|----|
| 1 | 1 | 1 | 1 | 1 | 1 | 4 | 1 | 1 | 4 | 4 |
| 2 | 1 | 1 | 1 | 2 | 2 | 4 | 2 | 2 | 4 | 4 |
| 3 | 1 | 1 | 1 | 3 | 3 | 4 | 3 | 3 | 4 | 4 |
| 4 | 1 | 1 | 1 | 4 | 4 | 4 | 4 | 4 | 4 | 4 |
_
_ORDER BY
_句を使用するウィンドウ関数に適用される暗黙的なフレームについて考える人はほとんどいません。この場合、ウィンドウはデフォルトでフレーム_ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
_になります。次のように考えてください。
v = 1
_のある行では、順序付けられたウィンドウのフレームはv IN (1)
にまたがりますv = 2
_のある行では、順序付けられたウィンドウのフレームはv IN (1, 2)
にまたがりますv = 3
_のある行では、順序付けられたウィンドウのフレームはv IN (1, 2, 3)
にまたがりますv = 4
_のある行では、順序付けられたウィンドウのフレームはv IN (1, 2, 3, 4)
にまたがりますその動作を防止したい場合は、2つのオプションがあります。
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
_句を使用するORDER BY
_句を使用しない(MAX(v) OVER()
として)詳細は LEAD()
、LAG()
、FIRST_VALUE()
およびLAST_VALUE()
に関するこの記事で説明されています
ウィンドウ関数としてのmax()
の結果は、フレーム定義に基づいています。
デフォルトのフレーム定義(_ORDER BY
_を使用)は、フレームの先頭から現在の行の最後のピア(現在の行および場合によってはより多くの行のランキングを含む)等しいに従って_ORDER BY
_)。 _ORDER BY
_がない場合(私の回答のようにあなたが参照している場合)、または_ORDER BY
_がパーティションのすべての行を等しいものとして扱う場合(最初の例のように)、パーティションのすべての行はピアです、およびmax()
は、パーティションのすべての行に対して同じ結果を生成し、パーティションのall行を効果的に考慮します。
デフォルトのフレーミングオプションは_
RANGE UNBOUNDED PRECEDING
_で、これは_RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
_と同じです。 _ORDER BY
_を使用すると、フレームはパーティションの先頭からすべての行になるように設定されます現在の行の最後のピアまで。 _ORDER BY
_がない場合、すべての行が現在の行のピアになるため、パーティションのすべての行がウィンドウフレームに含まれます。
大胆な強調鉱山。
単純な解決策は、ウィンドウ定義で_ORDER BY
_を省略することです-参照している例で示したように。
マニュアルの Window Function Calls の章にあるフレーム仕様に関するすべての気の毒な詳細。