我有许多品牌的产品,用户可以喜欢(多对多),用户也可以关注品牌。对于主页,我需要用户添加到收藏夹的所有产品以及用户跟随的品牌产品。
我已经提供了以下SQL查询,但是它的工作方式并不像预期的那样 - 它只返回来自后续品牌并且在收藏夹中同时出现的产品。
SELECT * FROM products
INNER JOIN favorites ON products.id = favorites.favorable_id
INNER JOIN followings ON products.merchant_id = followings.followable_id
WHERE favorites.favorable_type = 'Product' AND favorites.user_id = ?
AND followings.followable_type = 'Merchant' AND followings.user_id = ?
如何正确修复查询? 提前谢谢。
编辑: 我将拥有10k +产品,1k +用户。所以我需要最快的执行时间查询。
答案 0 :(得分:3)
一种“简单”方法(仅修改现有查询)可能是将INNER JOIN
转换为LEFT JOIN
并检查at least one of the two joined successfully
中的WHERE
子句...
SELECT
*
FROM
products
LEFT JOIN
favorites
ON products.id = favorites.favorable_id
AND favorites.favorable_type = 'Product'
AND favorites.user_id = ?
LEFT JOIN
followings
ON products.merchant_id = followings.followable_id
AND followings.followable_type = 'Merchant'
AND followings.user_id = ?
WHERE
favorites.user_id IS NOT NULL
OR followings.user_id IS NOT NULL
这样做的缺点是product
表中的 每条 记录都必须由WHERE
子句检查。
如果该表很小,或者您通常以任何方式返回表的“大”部分,这可能没问题。但是,如果您只返回表格的“小”部分,则可能需要对此进行优化,例如使用UNION
的两个查询,如问题标题所暗示的那样......
SELECT
products.*
FROM
products
INNER JOIN
favorites
ON products.id = favorites.favorable_id
AND favorites.favorable_type = 'Product'
AND favorites.user_id = ?
UNION
SELECT
products.*
FROM
products
INNER JOIN
followings
ON products.merchant_id = followings.followable_id
AND followings.followable_type = 'Merchant'
AND followings.user_id = ?
此处的INNER JOIN
每个LEFT JOIN
可能明显快于基于followings(user_id, followable_type)
的整个查询,因为可能会使用favorites(user_id, favorable_type)
和{{1}}上的索引。
答案 1 :(得分:0)
尝试替换
INNER JOIN followings ON products.merchant_id = followings.followable_id
与
left JOIN followings ON favorites.favorable_id = followings.followable_id
答案 2 :(得分:0)
select p.*
from products as p
where
exists (
select *
from favorites as f
where f.favorable_id = p.id and f.favorable_type = 'Product' and f.user_id = ?
) or
exists (
select *
from followings as f
where f.followable_id = p.merchant_id and f.followable_type = 'Merchant' and f.user_id = ?
)
答案 3 :(得分:0)
SELECT * FROM products p
LEFT JOIN favorites ON products.id = favorites.favorable_id and favorites.favorable_type = 'Product' AND favorites.user_id = ?
LEFT JOIN followings ON products.merchant_id = followings.followable_id and followings.followable_type = 'Merchant' AND followings.user_id = ?
WHERE favorites.user_id is not null or followings.user_id is not null
答案 4 :(得分:0)
你可以试试这个:
select p.*
from products as p
where
p.id in (
select f.favorable_id
from favorites as f
where f.favorable_type = 'Product' and f.user_id = ?
)
or p.merchant_id in (
select f.followable_id
from followings as f
where f.followable_type = 'Merchant' and f.user_id = ?
)