1

私はSQLのクエリを作成しましたが、それは本当に重く、それを最適化する方法が本当にわかりません。説明は次のとおりです。

SELECT tyds.user_tyd, 
       tyds.product_tyd, 
       tyds.action_tyd, 
       products.price_product, 
       data_8, 
       data_9, 
       avg_8, 
       sum_9 
FROM   tyds 
       INNER JOIN products 
               ON tyds.product_tyd = products.id_product 
       INNER JOIN (SELECT product_tyd, 
                          Avg(data_tyd) AS avg_8 
                   FROM   tyds 
                   WHERE  action_tyd = 8 
                   GROUP  BY product_tyd) Agg_1 
               ON Agg_1.product_tyd = tyds.product_tyd 
       INNER JOIN (SELECT product_tyd, 
                          Sum(data_tyd) AS sum_9 
                   FROM   tyds 
                   WHERE  action_tyd = 9 
                   GROUP  BY product_tyd) Agg_2 
               ON Agg_2.product_tyd = tyds.product_tyd 
       INNER JOIN (SELECT product_tyd, 
                          data_tyd AS data_8 
                   FROM   tyds 
                   WHERE  user_tyd = 3 
                          AND action_tyd = 8) Agg_3 
               ON Agg_3.product_tyd = tyds.product_tyd 
       INNER JOIN (SELECT product_tyd, 
                          data_tyd AS data_9 
                   FROM   tyds 
                   WHERE  user_tyd = 3 
                          AND action_tyd = 9) Agg_4 
               ON Agg_4.product_tyd = tyds.product_tyd 
WHERE  tyds.user_tyd = 3 
       AND tyds.action_tyd = 1 
GROUP  BY tyds.product_tyd 

多くのものを取得する必要があるため、このすべての結合:tyds.user_tyd = 3 tyds.action_tyd = 1でid_userを定義します。これは、前のid_userをtyds.action_tyd=1としてtyds.product_tydでグループ化するためです。

次に、必要なもの:-data_8はtyds.data_tydの値です。WHEREuser_tyd = 3 AND action_tyd =8-data_9と同じです。

-AVGとCOUNTの場合、tyds.user_tyd条件をスキップし、id_productでのみグループ化します。

実際、このクエリは機能していますが、非常に重く、SELECTが多すぎると思います...

1か月前に同様の質問をしましたが、アーキテクチャを確認する必要があったため、申し訳ありません...

どうもありがとう。

e1:MySQLを使用しています

4

2 に答える 2

2

実際には、これらの結合とサブクエリのすべてが必要なわけではありません。WHEREを使用して、ロジックを-clausesからfield-listに移動することで、それらのほとんどを排除できます。CASE

SELECT 3 AS user_tyd, tyds.product_tyd, 1 AS action_tyd,
       products.price_product,
       MAX(CASE WHEN user_tyd = 3 AND action_tyd = 8 THEN data_tyd END) data_8,
       MAX(CASE WHEN user_tyd = 3 AND action_tyd = 9 THEN data_tyd END) data_9,
       AVG(CASE WHEN action_tyd = 8 THEN data_tyd END) AS avg_8,
       SUM(CASE WHEN action_tyd = 9 THEN data_tyd END) AS sum_9
  FROM tyds
  JOIN products
    ON tyds.product_tyd = products.id_product
 WHERE tyds.product_tyd IN
         ( SELECT product_tyd
             FROM tyds
            WHERE tyds.user_tyd = 3
              AND tyds.action_tyd = 1
         )
 GROUP
    BY tyds.product_tyd
;

(注:MAX(...)3行目と4行目のは、null以外の値をnull値よりも優先させる方法にすぎません。)

これが実際に速いかどうかを確認するためにテストする必要がありますが、私はそれが速いと確信しています。

于 2012-08-23T19:16:48.727 に答える
1

簡単な例、最初のAgg_%のみ

create temporary table Agg_1
(
  product_tyd ...,
  avg_8 ...
)

insert into Agg_1
SELECT product_tyd, AVG(data_tyd) AS avg_8 FROM tyds WHERE action_tyd = 8 
GROUP BY product_ty

SELECT  tyds.user_tyd, tyds.product_tyd, tyds.action_tyd, products.price_product,
data_8, data_9, avg_8, sum_9 
FROM tyds 
INNER JOIN products 
ON tyds.product_tyd = products.id_product 
INNER JOIN Agg_1 ON Agg_1.product_tyd = tyds.product_tyd
...

さて、あなたはMysqlに取り組んでいるようです。MySqlで動作するかどうかはわかりませんが、MySqlの第一人者ではありません。しかし、私はそれがoracleとsybaseで動作すると確信しています。

于 2012-08-23T19:17:22.317 に答える