SELECT m.title , m.run_time FROM movie m WHERE m.run_time < (SELECT AVG (run_time) FROM movie) *1.1 AND m.run_time > (SELECT AVG (run_time) FROM movie) *0.9;
postgresql では 4.6 から 8 のコストがかかります
基本的に、平均実行時間の 10% 以内にある映画のタイトルと実行時間を選択します。ムービー テーブルは次のようになります。
CREATE TABLE MOVIE
(
title varchar(40) NOT NULL,
production_year smallint NOT NULL,
country varchar(20) NOT NULL,
run_time smallint NOT NULL,
major_genre varchar(15) ,
CONSTRAINT pk_movie PRIMARY KEY(title,production_year)
);
101 件のエントリがあります。
「SELECT AVG (run_time) FROM movie」が2回使われているので、変数に平均を入れて、2回目のクエリでその変数を参照することを考えました。Mysql は次のように表示され、実行されます。2 つのコマンドの合計時間は、上記の参照クエリよりも短くなります。
SET @average = (SELECT AVG (run_time) FROM movie);
SELECT m.title , m.run_time FROM movie m WHERE m.run_time < @average *1.1 AND m.run_time > @average *0.9;
さて、これをpostgresqlで同等に行うにはどうすればよいでしょうか? 以下に私の試みをリストしました
postgresql で変数を作成しようとすると、次のようになります。
\set average (SELECT AVG (run_time) FROM movie);
これは機能します。しかし、次の行:
SELECT m.title , m.run_time FROM movie m WHERE m.run_time < :average *1.1 AND m.run_time > :average *0.9;
ERROR: syntax error at or near "FROMmovie"
LINE 1: ...OM movie m WHERE m.run_time < (SELECTAVG(run_time)FROMmovie)...
これは、\set が文字列変数のようにコマンドを文字どおりに配置し、mysql とは異なり、それを評価しないためだと思います。
だから私は一時テーブルを作ろうとします
CREATE TEMP TABLE temptable ( theaverage float );
insert into temptable ( SELECT AVG (m.run_time) FROM movie m );
SELECT m.title , m.run_time FROM movie m WHERE m.run_time < (Select * from temptable) *1.1 AND m.run_time > (Select * from temptable) *0.9;
これらは機能します。しかし、(測定)性能は、あまり良くありません。
explain analyze CREATE TEMP TABLE temptable ( theaverage float ); //cannot analyze this/does not work/syntax error happens.
ERROR: syntax error at or near "float"
LINE 1: ...in analyze CREATE TEMP TABLE temptable ( theaverage float );
explain insert into temptable ( SELECT AVG (m.run_time) FROM movie m ); //costs 2.3ish
explain SELECT m.title , m.run_time FROM movie m WHERE m.run_time < (Select theaverage from temptable) *1.1 AND m.run_time > (Select theaverage from temptable) *0.9;
//コストは 63 から 66 ですね。これにより、最適化されていないクエリ (4.6 ~ 8) よりも大幅にコストが高くなります。
SELECT INTO も試しましたが、目的に合わせて正しく使用する方法がわかりませんでした。
それで、私は質問を繰り返します、最適化されたバージョンの
"SELECT m.title , m.run_time FROM movie m WHERE m.run_time < (SELECT AVG (run_time) FROM movie) *1.1 AND m.run_time > (SELECT AVG (run_time) FROM movie) *0.9;"
おそらくpostgresqlで変数を使用し、かつパフォーマンス測定を使用することによって?