1

別の属性でグループ化された関数の MIN() 値を見つけるために、複雑でコストのかかるクエリを実行しています。しかし、必要なのは値だけではありません。それを生成するエントリと値が必要です。

私の現在の疑似クエリは次のようになります。

SELECT MIN(COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2)) FROM (prefiltering) as a GROUP BY a.group_att;

しかし、私は欲しいa.*MIN(COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2))私の結果として。

私が考えることができる唯一の方法は、この醜い獣を使用することです:

SELECT a1.*, COSTLY_FUNCTION(a1.att1,a1.att2,$v1,$v2)
FROM (prefiltering) as a1 
WHERE COSTLY_FUNCTION(a1.att1,a1.att2,$v1,$v2) = 
  (SELECT MIN(COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2)) FROM (prefiltering) as a GROUP BY a.group_att) 

しかし今、私は prefiltering_query を 2 回実行しており、コストのかかる関数を 2 回実行する必要があります。これはばかげており、ここで何か深刻な問題を抱えていることを願っています。

考えられる解決策は?:

今、次のものを含む一時テーブルを作成できることに気付きました。

(SELECT a1.*, COSTLY_FUNCTION(a1.att1,a1.att2,$v1,$v2) as complex FROM (prefiltering) as a1)

次に、MIN() をサブクエリとして実行し、コストを大幅に削減して比較します。それは行く方法ですか?

4

2 に答える 2

1

一時テーブル ソリューションの問題は、同じクエリで 2 回使用することを避ける方法が見つからないことです。

ただし、実際の永続テーブル (おそらく を使用ENGINE = MEMORY) を使用する場合は、動作するはずです。サブクエリをFROM句に移動することもできます。これにより、より効率的な場合があります。

CREATE TABLE temptable ENGINE = MEMORY
  SELECT a1.*,
    COSTLY_FUNCTION(a1.att1,a1.att2,$v1,$v2) AS complex
  FROM prefiltering AS a1;

CREATE INDEX group_att_complex USING BTREE
  ON temptable (group_att, complex);

SELECT a2.*
FROM temptable AS a2
  NATURAL JOIN (
    SELECT group_att, MIN(complex) AS complex
    FROM temptable GROUP BY group_att
  ) AS a3;

DROP TABLE temptable;

(インデックスなしでも試すことができますが、インデックスを使用すると高速になると思います。)

編集:もちろん、1 つの一時テーブルではうまくいかない場合は、常に 2 つを使用できます。

CREATE TEMPORARY TABLE temp1
  SELECT *, COSTLY_FUNCTION(att1,att2,$v1,$v2) AS complex
  FROM prefiltering;

CREATE INDEX group_att_complex ON temp1 (group_att, complex);

CREATE TEMPORARY TABLE temp2
  SELECT group_att, MIN(complex) AS complex
  FROM temp1 GROUP BY group_att;

SELECT temp1.* FROM temp1 NATURAL JOIN temp2;

(繰り返しになりますが、インデックスの有無にかかわらず試してみてください。実行EXPLAINしたとき、MySQL は最終的なクエリにインデックスをまったく使用したくないように見えましたが、それは私のテスト データ セットがとにかく、これで遊んでみたいなら、ここに SQLize へのリンクがありCONCAT()ます; 私はあなたの高価な関数の代役を務めていました.)

于 2011-10-15T19:57:50.013 に答える
0

HAVING句を使用して、そのMIN値に加えて列を取得できます。例えば:

SELECT a.*, COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2) FROM (prefiltering) as a GROUP BY a.group_att HAVING MIN(COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2)) = COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2);
于 2011-10-15T19:19:02.450 に答える