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
返回不同的结果集,为什么?
答案 0 :(得分:4)
第一个查询在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_options
或cscart_product_options_variants
表中选择数据,因此您可以从查询中删除这些数据。您还应该查看带有子查询的LEFT JOIN是否合适;我认为你更想要一个内部联接。可能会有更多工作可以改善绩效。
答案 1 :(得分:1)
除了乔纳森所说的。在第一个查询中,WHERE强制它没有得到任何结果,除非(pb.bike_id = 111或vb.bike_id = 111)为真。在第二个查询中,即使只有一行可以通过LEFT JOIN加入,您将获得所有DISTINCT [product_id]。
如果您从第二个查询到第一个查询获得了大量结果,那就是这样。更简单的方法是在SELECT中加入更多内容:
SELECT p.product_id, pb.bike_id ...
如果你这样做,你会注意到第一个查询在它显示的每个产品中都有111个,但是第二个查询将为pb.bike_id提供很多NULL值。
有意义吗?