如何使用多个选择查询优化UNION mysql查询?

时间:2013-07-09 08:15:22

标签: php mysql join query-optimization union

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

  1. 尺寸,颜色,类别,公司应与当前产品相匹配
  2. 尺寸,颜色,类别应与当前产品相匹配
  3. 尺寸,颜色应与当前产品相匹配
  4. 尺寸应与当前产品相匹配
  5. 我的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的产品,则需要首先按随机顺序列出。同样,我们需要列出与其下方其他条件匹配的产品。

    提前致谢!

1 个答案:

答案 0 :(得分: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