【问题标题】:How to optimize a UNION mysql query with multiple select queries?如何使用多个选择查询优化 UNION mysql 查询?
【发布时间】:2013-07-06 18:21:41
【问题描述】:

我要求在产品详细信息页面中显示类似产品,以便列出的产品应以分层方式与当前产品属性匹配,如下所示

  1. 尺寸、颜色、类别、公司应与当前产品匹配
  2. 尺寸、颜色、类别应与当前产品匹配
  3. 尺寸、颜色应与当前产品相匹配
  4. 尺寸应与当前产品匹配

我的sql查询如下:

(SELECT pd.product_id, pd.name, p.price 
        FROM mg_product_description pd 
            JOIN `mg_product` p ON p.product_id = pd.product_id 
        WHERE 
            pd.size_id = '33' AND 
            pd.color_id = '2' AND 
            pd.category_id = '3' AND 
            pd.company_id = '1'  AND 
            pd.product_id != '53'  AND 
            p.status = '1' 
            ORDER BY RAND() LIMIT 10 
    )
        UNION
    (SELECT pd.product_id, pd.name, p.price 
        FROM mg_product_description pd 
            JOIN `mg_product` p ON p.product_id = pd.product_id 
        WHERE 
            pd.size_id = '33' AND 
            pd.color_id = '2' AND 
            pd.category_id = '3'  AND 
            pd.product_id != '53'  AND 
            p.status = '1' 
            ORDER BY RAND() LIMIT 10 
    )
        UNION
    (SELECT pd.product_id, pd.name, p.price 
        FROM mg_product_description pd 
            JOIN `mg_product` p ON p.product_id = pd.product_id 
        WHERE 
            pd.size_id = '33' AND 
            pd.color_id = '2' AND 
            pd.product_id != '53'  AND 
            p.status = '1' 
            ORDER BY RAND() LIMIT 10 
    )
        UNION
    (SELECT pd.product_id, pd.name, p.price 
        FROM mg_product_description pd 
            JOIN `mg_product` p ON p.product_id = pd.product_id 
        WHERE 
            pd.size_id = '33' AND 
            pd.product_id != '53' AND 
            p.status = '1'
            ORDER BY RAND() LIMIT 10 
    )

53 - 当前产品 ID 和状态表示可用!

有没有办法优化上面的查询?

需要备注输出:我们需要 10 个类似的产品。如果有 4 个符合条件 1 的产品,则需要先随机列出。同样,我们需要在其下方列出符合其他条件的产品。

提前致谢!

【问题讨论】:

  • ORDER BY RAND() 通常很慢,无论如何你需要提供解释输出。
  • 感谢您的评论。我已经更新了问题。
  • 抱歉不清楚,我在说,dev.mysql.com/doc/refman/5.0/en/explain.html
  • “优化”是指上述查询的“提高性能”还是“降低复杂性”?
  • 两者。提高性能的优先级!!

标签: php mysql join query-optimization union


【解决方案1】:

继续使用 ORDER BY RAND()(效率不高)然后一个非常基本的改进是为每个子句添加一个优先级,将 order 子句移到最后,因此只需要它一次。

(SELECT pd.product_id, pd.name, p.price , 1 AS recpriority
        FROM mg_product_description pd 
            JOIN `mg_product` p ON p.product_id = pd.product_id 
        WHERE 
            pd.size_id = '33' AND 
            pd.color_id = '2' AND 
            pd.category_id = '3' AND 
            pd.company_id = '1'  AND 
            pd.product_id != '53'  AND 
            p.status = '1' 
    )
        UNION
    (SELECT pd.product_id, pd.name, p.price , 2 AS recpriority
        FROM mg_product_description pd 
            JOIN `mg_product` p ON p.product_id = pd.product_id 
        WHERE 
            pd.size_id = '33' AND 
            pd.color_id = '2' AND 
            pd.category_id = '3'  AND 
            pd.product_id != '53'  AND 
            p.status = '1' 
    )
        UNION
    (SELECT pd.product_id, pd.name, p.price , 3 AS recpriority
        FROM mg_product_description pd 
            JOIN `mg_product` p ON p.product_id = pd.product_id 
        WHERE 
            pd.size_id = '33' AND 
            pd.color_id = '2' AND 
            pd.product_id != '53'  AND 
            p.status = '1' 
    )
        UNION
    (SELECT pd.product_id, pd.name, p.price , 4 AS recpriority
        FROM mg_product_description pd 
            JOIN `mg_product` p ON p.product_id = pd.product_id 
        WHERE 
            pd.size_id = '33' AND 
            pd.product_id != '53' AND 
            p.status = '1'
    )
    ORDER BY recpriority, RAND() LIMIT 10 

然后可以通过以下方式在不需要工会的情况下完成:-

SELECT pd.product_id, 
    pd.name, 
    p.price , 
    CASE
        WHEN pd.color_id = '2' AND pd.category_id = '3' AND pd.company_id = '1'  THEN 1 
        WHEN pd.color_id = '2' AND pd.category_id = '3' THEN 2 
        WHEN pd.color_id = '2' THEN 3 
        ELSE 4 
    END AS recpriority
FROM mg_product_description pd 
JOIN `mg_product` p ON p.product_id = pd.product_id 
WHERE pd.size_id = '33' 
AND pd.product_id != '53' 
AND p.status = '1'
ORDER BY recpriority, RAND() 
LIMIT 10 

【讨论】:

  • 太棒了!非常感谢 :) !有没有其他方法可以选择随机行(...使用 ORDER BY RAND() (效率不高)...)?
  • 是的。我使用了更有效的方法来返回单行(基本上你会在最小和最大 id 之间获得一个随机值,然后选择该随机值上方的第一个 id),但不确定在检索 10 时可以使用的方法. 这篇文章可能对您确定一个好的随机方法有用 - stackoverflow.com/questions/4329396/…
猜你喜欢
  • 2017-12-06
  • 1970-01-01
  • 2012-12-18
  • 1970-01-01
  • 2017-02-08
  • 1970-01-01
  • 2019-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多