2016-11-25 18 views
0

私はeコマーススクリプトをやっています。MySqlの最適化他のテーブルの列に最大値を持つ行のみを選択

私はテーブル「commerce_product」を持っています。

私はテーブル「commerce_product_price_index」を持っています。この表では、各製品ごとに異なる価格をすべて保存しています。 価格は、customer_group、通貨、国、ジオゾーン、顧客、日付期間によって異なります。

ここではこのテーブルの例を示します。

+------+--------------+--------------------+--------------+-------------+-------------+----------+-------------+--------------+--------------+-------------+------------------+------------------+ 
| id | product_id | customer_group_id | currency_id | country_id | geozone_id | user_id | time_from | time_to  | min_price | max_price | final_min_price | final_max_price | 
+------+--------------+--------------------+--------------+-------------+-------------+----------+-------------+--------------+--------------+-------------+------------------+------------------+ 
| 1 | 1   | 0     | 0   | 0   | 0   | 0  | 1479942000 | 1480460400 | 500   | 500   | 300    | 300    | 
| 2 | 1   | 1     | 0   | 0   | 0   | 0  | 1479942000 | 1480460400 | 500   | 500   | 250    | 250    | 
| 3 | 1   | 2     | 0   | 0   | 0   | 0  | 1479942000 | 1480460400 | 500   | 500   | 200    | 200    | 
| 4 | 1   | 3     | 0   | 0   | 0   | 0  | 1479942000 | 1480460400 | 500   | 500   | 100    | 100    | 
+------+--------------+--------------------+--------------+-------------+-------------+----------+-------------+--------------+--------------+-------------+------------------+------------------+ 

この例では、4種類の価格の製品があります。

まず、各価格のスコアを計算するために選択します。

SELECT 
    IF (1480090146 >= `time_from` AND 1480090146 <= `time_to`, 1, 0) + 
    IF (`customer_group_id` = 3, 2, 0) + 
    IF (`geozone_id` = 2, 4, 0) + 
    IF (`country_id` = 73, 8, 0) + 
    IF (`currency_id` = 1, 16, 0)+ 
    IF (`user_id` = 2352, 32, 0) AS score, 
    `cppi`.* 
    FROM 
     `commerce_product_price_index_2` AS `cppi` 
    WHERE 
     (geozone_id IN('2', 0)) 
     AND (country_id IN('73', 0)) 
     AND (currency_id IN('1', 0)) 
     AND (customer_group_id IN('3', 0)) 
     AND (user_id IN('2352', 0)) 
     AND (cppi.time_from <= 1480090146) 
     AND (cppi.time_to >= 1480090146) 
    ORDER BY `score` desc 

私は新しいカラムと2つの結果は

+--------+------+--------------+--------------------+--------------+-------------+-------------+----------+-------------+--------------+--------------+-------------+------------------+------------------+ 
| score | id | product_id | customer_group_id | currency_id | country_id | geozone_id | user_id | time_from | time_to  | min_price | max_price | final_min_price | final_max_price | 
+--------+------+--------------+--------------------+--------------+-------------+-------------+----------+-------------+--------------+--------------+-------------+------------------+------------------+ 
| 3  | 1 | 1   | 0     | 0   | 0   | 0   | 0  | 1479942000 | 1480460400 | 500   | 500   | 300    | 300    | 
| 1  | 2 | 1   | 1     | 0   | 0   | 0   | 0  | 1479942000 | 1480460400 | 500   | 500   | 250    | 250    | 
+--------+------+--------------+--------------------+--------------+-------------+-------------+----------+-------------+--------------+--------------+-------------+------------------+------------------+ 

を獲得しており、この結果に私は良い価格を得るために最大のスコアを選択します。

SELECT 
    `cppi2`.*, 
    MAX(score) 
FROM (
    SELECT 
     `cppi`.*, 
     IF (1480090146 >= `time_from` AND 1480090146 <= `time_to`, 1, 0) + 
     IF (`customer_group_id` = 3, 2, 0) + 
     IF (`geozone_id` = 2, 4, 0) + 
     IF (`country_id` = 73, 8, 0) + 
     IF (`currency_id` = 1, 16, 0)+ 
     IF (`user_id` = 2352, 32, 0) AS score 
     FROM 
      `commerce_product_price_index` AS `cppi` 
     WHERE 
      (geozone_id IN('2', 0)) 
      AND (country_id IN('73', 0)) 
      AND (currency_id IN('1', 0)) 
      AND (customer_group_id IN('3', 0)) 
      AND (user_id IN('2352', 0)) 
      AND (cppi.time_from <= 1480090146) 
      AND (cppi.time_to >= 1480090146) 
     ORDER BY `score` desc 

    ) AS `cppi2` 
GROUP BY `product_id` 

私の製品テーブルを選択した後、私はこの要求に参加します。

私の質問です:これを行うには良い方法ですか?

私の製品テーブルには13000行があります。 私の価格インデックステーブルには50000行があります。

あなたに最適なソリューションがありますか?

+0

http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-very-simple-あなたのコメントはsql-query – Strawberry

答えて

0

time_fromtime_toの部分をスコア計算から削除できるようですが、これはWHERE句の一部なので、スコア計算から削除できます。

ORDER BY score - MAX(score)の世話をする必要はありません。

あなたが必要な列だけを選択するのではなくSELECT cppi.*

あなたのソリューションは、私には合理的なようで考慮すべきです。他の解決策には、mysqlを使用するのではなく、コード内のスコアを計算すること(または、if/else/case文を使用してuser_id、customer_group_idなどを順番にチェックすること)があります。

アトリビュートが一致しているかどうかを計算したブール値フラグを使用して解決する方法を考え出しましたが、GROUP BY product_idで動作させることができませんでした。そこに解決策があるかもしれないが、私はそれがもっと速くなるとは思わない。

+0

です。 テンポリーテーブルを作成する方がいいでしょうか? – anardil

関連する問題