質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

763閲覧

postgresにおけるウインドウ関数の実行タイミングについて

Carlos_is_only

総合スコア42

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

1クリップ

投稿2021/08/23 16:49

sqlの実行タイミングについて不明点がございます。まず
テーブルは以下のような設計となっております。

sql

1DROP TABLE IF EXISTS item_purchase_anlytics; 2create table item_purchase_anlytics( 3item_name char(16), 4item_category char(16), 5action_date date, 6place char(8), 7user_id char(8), 8price int 9); 10insert into item_purchase_anlytics values 11 ('サバ','food','2019-03-29','Store A','UID0001',280), 12 ('しょう油','food','2019-03-29','Store A','UID0001',280), 13 ('サバ','food','2019-03-30','Store A','UID0001',350), 14 ('サバ','food','2019-03-30','Store A','UID0001',350), 15 ('卵','food','2019-03-30','Store A','UID0001',200), 16 ('しょう油','food','2019-03-30','Store A','UID0001',200), 17 ('鶏肉','food','2019-04-01','Store A','UID0001',450), 18 ('卵','food','2019-04-04','Store A','UID0001',280), 19 ('卵','food','2019-04-06','Store A','UID0001',280), 20 ('卵','food','2019-04-09','Store A','UID0001',280), 21 ('サバ','food','2019-04-10','Store A','UID0004',280), 22 ('しょう油','food','2019-04-10','Store A','UID0001',280), 23 ('卵','food','2019-04-10','Store A','UID0001',280), 24 ('卵','food','2019-04-12','Store A','UID0001',280), 25 ('卵','food','2019-04-12','Store A','UID0001',280), 26 ('鶏肉','food','2019-04-12','Store A','UID0001',450), 27 ('サバ','food','2019-04-13','Store A','UID0001',280), 28 ('しょう油','food','2019-04-13','Store A','UID0001',280), 29 ('深皿','zakka','2019-04-14','Store A','UID0003',780), 30 ('しょう油','food','2019-04-14','Store A','UID0003',280), 31 ('深皿','zakka','2019-04-14','Store A','UID0003',980), 32 ('卵','food','2019-04-15','Store A','UID0001',280), 33 ('サバ','food','2019-04-17','Store A','UID0001',280), 34 ('サバ','food','2019-04-18','Store A','UID0001',280), 35 ('深皿','zakka','2019-04-23','Store A','UID0002',980);

実行したsqlは以下になります。

sql

1 2以下のようなsqlを実行しました。 3 4SELECT 5 action_date, 6 SUM(price) AS amount_price,      -- ① 7 AVG(SUM(price)) OVER(         -- ② 8 ORDER BY 9 action_date 10 ROWS BETWEEN 6 preceding 11 AND CURRENT ROW 12 ) AS moving_average 13FROM 14 item_purchase_anlytics 15GROUP BY 16 action_date 17ORDER BY 18 action_date 19;

実行結果を確認したところ
①についてはGROUP BYしたグループごとに合計値を取得しているようなのですが
問題は②についてです。
通常ウインドウ関数についてはselect時に実行するつまり今回で言うとところのGROUP BYした後の最後のselect文の実行時に実行されるという認識です。
よって②のSUM(price)はGROUP BY action_dateでグループした後のacton_dateごとでグループした後の範囲の中での合計値を取得していると思います。
「AVG(SUM(price)) OVER(・・・」については実行結果を確認するとaction_dateを並べ変えてかつその合計値つまり①の実行結果を
出力した後のある行の6行前の平均値を取得しているように見えます。

ウィンドウ関数の実行タイミングはsqlのウインドウ関数以外のselect文が実行された後のデータに対してウインドウ関数が実行されるという認識で正しいでしょうか?

実行タイミングが読めないでウインドウ関数の実行タイミングがよくわからないのでどなたか教えていただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ウィンドウ関数の実行タイミングはsqlのウインドウ関数以外のselect文が実行された後のデータに対して
ウインドウ関数が実行されるという認識で正しいでしょうか?

はい。仰るとおりです。
ただし、
省略可能な引数をスキップした場合や上位で指定する句の記述を変更した場合の動作は
少し注意なさったほうがいいでしょう。

以下に掲載するSQL文の結果がすぐに想像できて
全ての列において実際の結果も合致していたら...けっこう凄いと思います。

SQL

1SELECT 2 ROW_NUMBER() OVER() As rid, 3 action_date, 4 STRING_AGG(cast(price as varchar), ',') As array_to_price, 5 AVG(MAX(price)) OVER( 6 ORDER BY 7 action_date DESC 8 ROWS BETWEEN 6 preceding 9 AND CURRENT ROW 10 ) AS moving_average 11FROM 12 item_purchase_anlytics 13GROUP BY 14 action_date 15ORDER BY 16 action_date 17;
  • row_number関数は

射影1のため、値が昇順で表示されるかと思いきや
戻り値がパーティション内での行番号という性質と引数が無指定のため
射影4のORDER BY action_date DESCの結果に影響を受け、
射影2のaction_dateが昇順に並んでいるのにもかかわらず、戻り値が降順となります

  • 射影4のwindow関数で指定しているFRAME句(->OVER句->ORDER BY句)は

OVER句(->ORDER BY句)でaction_date列の並びを降順に指定しているため、
前のレコードではなく、後ろのレコードを6行分参照します

■結果

ridaction_datearray_to_pricemoving_averagemoving_averageの内部動作演算対象のrid
142019/3/29[280,280]314.2857143(280 + 280 + 280 + 280 + 450 + 350 + 280) / 78 から 14
132019/3/30[350,350,200,200]338.5714286(450 + 280 + 280 + 280 + 280 + 450 + 350) / 77 から 13
122019/4/1[450]328.5714286(280 + 450 + 280 + 280 + 280 + 280 + 450) / 76 から 12
112019/4/4[280]404.2857143(980 + 280 + 450 + 280 + 280 + 280 + 280) / 75 から 11
102019/4/6[280]404.2857143(280 + 980 + 280 + 450 + 280 + 280 + 280) / 74 から 10
92019/4/9[280]404.2857143(280 + 280 + 980 + 280 + 450 + 280 + 280) / 73 から 9
82019/4/10[280,280,280]404.2857143(280 + 280 + 280 + 980 + 280 + 450 + 280) / 72 から 8
72019/4/12[280,280,450]504.2857143(980 + 280 + 280 + 280 + 980 + 280 + 450) / 71 から 7
62019/4/13[280,280]513.3333333(980 + 280 + 280 + 280 + 980 + 280) / 61 から 6
52019/4/14[780,280,980]560(980 + 280 + 280 + 280 + 980) / 51 から 5
42019/4/15[280]455(980 + 280 + 280 + 280) / 41 から 4
32019/4/17[280]513.3333333(980 + 280 + 280) / 31 から 3
22019/4/18[280]630(980 + 280) / 21 から 2
12019/4/23[980]980(980) / 11 のみ

投稿2021/08/23 21:39

編集2021/08/23 22:33
mayu-

総合スコア335

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Carlos_is_only

2021/08/24 06:28

表まで作成していただいて・・・ 詳しいご説明誠にありがとうございます。
Carlos_is_only

2021/08/24 07:06

詳しいご説明をありがとうございました。 また新にSQLの質問をさせていただいたのでお時間が許せば是非そちらもご覧いただけると嬉しいです。
guest

0

ウィンドウ関数の実行タイミングはsqlのウインドウ関数以外のselect文が実行された後のデータに対してウインドウ関数が実行されるという認識で正しいです。

クエリの実行計画を見るとウインドウ関数が最後に実行されることが分かります。「データ検索→グルーピング→ソート→ウインドウ関数」の順で実行されます。

クエリの実行計画は「explain select(…)」で取得できます。

投稿2021/08/23 19:58

k.fujisawa

総合スコア29

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Carlos_is_only

2021/08/24 06:29

なるほど、クエリ実行計画を確認する方法がありましたね ご説明ありがとうございます。
Carlos_is_only

2021/08/24 07:06

詳しいご説明をありがとうございました。 また新にSQLの質問をさせていただいたのでお時間が許せば是非そちらもご覧いただけると嬉しいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問