1
select distinct p.product_id from cscart_products p 
    left join product_bikes pb on p.product_id = pb.product_id
    left join cscart_product_options po on po.product_id = p.product_id
    left join cscart_product_option_variants pov on pov.option_id = po.option_id
    left join variant_bikes vb on vb.variant_id = pov.variant_id
    where pb.bike_id = 111 or vb.bike_id = 111 

和:

select distinct p.product_id from cscart_products p 
    left join product_bikes pb on p.product_id = pb.product_id and pb.bike_id = 111
    left join cscart_product_options po on po.product_id = p.product_id
    left join cscart_product_option_variants pov on pov.option_id = po.option_id
    left join variant_bikes vb on vb.variant_id = pov.variant_id and vb.bike_id = 111

返回不同的结果集,为什么?

4

2 回答 2

3

第一个查询在 WHERE 子句中有一个 OR:

WHERE pb.bike_id = 111 OR vb.bike_id = 111

第二个查询实际上有 AND,而是通过条件:

LEFT JOIN product_bikes pb ON p.product_id = pb.product_id AND pb.bike_id = 111
...
LEFT JOIN variant_bikes vb ON vb.variant_id = pov.variant_id AND vb.bike_id = 111

额外的问题:有没有一种方法可以通过连接使其行为相同并受益于较小的连接以提高性能?

有一种方法可以编写查询,但不一定更快,因为该方法(我正在考虑)使用 UNION:

select distinct p.product_id from cscart_products p 
    left join product_bikes pb on p.product_id = pb.product_id and pb.bike_id = 111
    left join cscart_product_options po on po.product_id = p.product_id
    left join cscart_product_option_variants pov on pov.option_id = po.option_id
    left join variant_bikes vb on vb.variant_id = pov.variant_id -- and vb.bike_id = 111
UNION
select distinct p.product_id from cscart_products p 
    left join product_bikes pb on p.product_id = pb.product_id -- and pb.bike_id = 111
    left join cscart_product_options po on po.product_id = p.product_id
    left join cscart_product_option_variants pov on pov.option_id = po.option_id
    left join variant_bikes vb on vb.variant_id = pov.variant_id and vb.bike_id = 111

可能有更好的方法,例如您有一个 UNION 子查询,如下所示:

SELECT DISTINCT p.product_id
  FROM      cscart_products                AS p 
  LEFT JOIN cscart_product_options         AS po  ON po.product_id = p.product_id
  LEFT JOIN cscart_product_option_variants AS pov ON pov.option_id = po.option_id
  LEFT JOIN (SELECT vb.product_id FROM variant_bikes AS vb WHERE vb.bike_id = 111
             UNION
             SELECT pb.product_id FROM product_bikes AS pb WHERE pb.bike_id = 111
            ) AS pv ON pv.product_id = p.product_id

由于您没有(在示例中)从cscart_product_optionsorcscart_product_options_variants表中选择数据,因此您可以从查询中消除这些数据。您还应该查看带有子查询的 LEFT JOIN 是否合适;我认为你更有可能想要一个内部连接。很可能有更多的工作可以做来提高性能。

于 2012-08-10T21:36:20.057 回答
0

除了乔纳森所说的。在第一个查询中,WHERE 强制您没有得到任何结果,除非 (pb.bike_id = 111 或 vb.bike_id = 111) 为真。在第二个查询中,您将获得所有 DISTINCT [product_id],即使只有一行能够通过 LEFT JOIN 连接。

如果您从第二个查询与第一个查询中得到很多结果,那就是这样。查看这一点的更简单方法是在您的 SELECT 中添加更多内容:

SELECT p.product_id, pb.bike_id ...

如果这样做,您会注意到,第一个查询将在它显示的每个产品中包含 111,但第二个查询将有很多 pb.bike_id 的 NULL 值。

说得通?

于 2012-08-10T21:47:42.557 回答