我正在寻找重写使用IN()子句的查询的最佳方法。 我想按照products_adjectives和products_interests中匹配次数最多的产品对结果进行排序。
我有5张桌子。
- products
title, price, description, etc.
- interests
interest_id, interest_name
- adjectives
adjective_id, adjective_name
- products_interests
product_id, interest_id
- products_adjectives
product_id, adjective_id
我目前正在使用此查询返回任何符合任何形容词或兴趣的产品。这是一个例子:
SELECT *
FROM products
LEFT JOIN products_adjectives
ON products_adjectives.product_id = products.id
LEFT JOIN products_interests
ON products_interests.product_id = products.id
WHERE products_adjectives.adjective_id IN (3,6,9,12,13) OR products_interests.interest_id IN (2,5,8,12,16,18)
GROUP BY products.id ORDER BY ABS(products.price)
目前,返回任何adjective_ids或interest_ids中存在的任何产品。该查询将返回任何具有任何adjective_id 3,6,9,12,13
或任何interest_id 2,5,8,12,16,18
的产品我想继续返回所有结果,但我希望它们按哪些产品包含大多数排序形容词或兴趣的匹配。因此,如果某个产品有形容词3,6,9,10,11
,那么我希望在形容为3,4,5,7,8
任何想法或方向都将不胜感激。如果我完全错了(使用IN()子句),请告诉我!
谢谢!
答案 0 :(得分:1)
我在想下面的内容。您缺少的关键想法是按count(*) DESC
排序。此查询的缺点是,如果兴趣或形容词表中没有匹配的记录,则不会提取任何产品。但是,由于我认为你是根据它们的相关性来提取东西,所以你不应该想要与零相关的产品。
SELECT *, count(*) as relevance
FROM products, products_adjectives, products_interests
WHERE products.id = products_interests.product_id
AND products.id = products_adjectives.product_id
AND (interest_id IN (14, 22, 78) OR adjective_id IN (8, 17, 26))
GROUP BY products.id
ORDER BY count(*) DESC, price ASC
答案 1 :(得分:0)
您的查询存在问题,因为您在给定产品的兴趣和形容词之间生成笛卡尔积。
解决此问题的最简单方法是计算不同的匹配。因此,以下order by
子句应该执行您想要的操作:
ORDER BY (count(distinct interest_id) + count(distinct adjective_id)) desc,
abs(product.price)
您可以通过其他方式解决此问题,例如计算子查询中的兴趣并计算子查询中的形容词。这将是推荐的方法,特别是如果名单变大。 (比方说,30个匹配的兴趣和30个匹配的形容词会产生一个中间表,产品差不多有一千行。)