1
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で変数を使用し、かつパフォーマンス測定を使用することによって?

4

1 に答える 1

2

このソリューションは変数を使用せず、PostgreSQL と MySQL の両方で機能します。

SELECT m.title, m.run_time
FROM movie m, 
    (SELECT avg(run_time) AS time FROM movie) a
WHERE m.run_time BETWEEN a.time * 0.9
                     AND a.time * 1.1

必須のSQLFiddle 。

列にインデックスを追加するrun_timeと、このクエリのパフォーマンスが向上することに注意してください (moviesテーブルが大きい場合)。

CREATE INDEX movies_run_time_idx ON movies(run_time);
于 2013-08-10T04:38:37.613 に答える