有没有比使用 UNION 更好的方法来组合两个查询?

Is there a better way to combine two queries other than using UNION?

我有两个相同的查询。我有一个案例,我想获取与一个集合相关的所有订单。我可以考虑使用 UNION 但是它太慢了。

查询 1: 在这里,我试图查询具有类型 2 的订单,这意味着 ref_id 正在引用一个变体。

订单 -> order_items -> varaints -> 产品 -> 行 -> 系列

SELECT
    `orders`.*
FROM
    `orders`
    LEFT JOIN `order_items` ON `orders`.`id` = `order_items`.`order_id`
    LEFT JOIN `variants` ON `order_items`.`ref_id` = `variants`.`id`
    LEFT JOIN `line_products` ON `variants`.`parent_id` = `line_products`.`product_id`
        AND `order_items`.`type` = 2
    LEFT JOIN `collection_line` ON `line_products`.`line_id` = `collection_line`.`line_id`
WHERE
    `collection_line`.`collection_id` = 55;

查询 2: 在这里,我试图查询商品类型为 1 的订单,这意味着 ref_id 正在引用产品。

订单 -> order_items -> 产品 -> 行 -> 系列

 SELECT
        `orders`.*
    FROM
        `orders`
        LEFT JOIN `order_items` ON `orders`.`id` = `order_items`.`order_id`
        LEFT JOIN `line_products` ON `order_items`.`ref_id` = `line_products`.`product_id`
            AND `order_items`.`type` = 1
        LEFT JOIN `collection_line` ON `line_products`.`line_id` = `collection_line`.`line_id`
    WHERE
        `collection_line`.`collection_id` = 55;

有什么方法可以组合和优化这两个查询吗?

您可以试试这个查询。

SELECT
    `orders`.*
FROM
    `orders`
    LEFT JOIN `order_items` ON `orders`.`id` = `order_items`.`order_id`
    LEFT JOIN `variants` ON `order_items`.`ref_id` = `variants`.`id`
    LEFT JOIN `line_products` ON `variants`.`parent_id` = `line_products`.`product_id`
        AND `order_items`.`type` IN ('1', '2')
    LEFT JOIN `collection_line` ON `line_products`.`line_id` = `collection_line`.`line_id`
WHERE
    `collection_line`.`collection_id` = 55;

使用IN

collection_line 听起来像是多对多映射 table。如果是这样,请遵循此处的索引建议:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table 特别是,需要 (collection_id, line_id) 上的复合索引。 line_products.

同样

p 需要 (line_id, product_id)
i: (ref_id, type, order_id)

LEFT 可能是不必要的;看看没有它是否能得到相同的结果。

这适用于单个订单,并且正在进行双左连接。一个用于变体,第二个用于默认行产品/系列。您让 WHERE 子句的每个实例都包含“collection_id = 55”,它出于需求目的将左联接更改为 INNER 联接。

因此,使用一个根级命令 table 两个左连接可以同时进行。唯一要添加的是“WHERE”子句。所以,无论NOT null的条件是哪个,都应该是一个或另一个。

select
      o.*
   from
      ( SELECT DISTINCT 
              oi.order_id
           FROM
              order_items oi
                 LEFT JOIN variants v
                    ON oi.ref_id = v.id
                    AND oi.type = 2
                    LEFT JOIN line_products lp
                        ON v.parent_id = lp.product_id
                        LEFT JOIN collection_line cl 
                            ON lp.line_id = cl.line_id
                            AND cl.collection_id = 55;
    
                 LEFT JOIN line_products lp2
                    ON oi2.ref_id = lp2.product_id
                    AND oi2.type = 1
                    LEFT JOIN collection_line cl2
                        ON lp2.line_id = cl2.line_id
                        AND cl2.collection_id = 55
           where
                  oi.type in ( 1,  2 )
              AND (    cl.collection_id = 55
                   OR  cl2.collection_id = 55 )) PQ
      JOIN Orders o
         on PQ.order_id = o.id

通过 OR,两边都不需要,但只要其中之一符合条件,顺序就应该 return。由于连接可能会为同一订单创建多个 return,并且您没有拉取状态。然后将这些唯一 ID 加入订单 table