我一直在尝试创建一个MySQL数据库查询,它将通过标记检索许多产品。我发现这个任务很容易,但是以正确的方式排序结果似乎比我预期的要复杂得多。 我有3个表product,tag和tag2product(它与前两个的id相关)并编写了以下查询:
SELECT product.id FROM product
LEFT OUTER JOIN tag2product ON product.id=tag2product.product_id
LEFT OUTER JOIN tag ON tag2product.tag_id = tag.id
WHERE tag.id=1 OR tag.id=2 OR tag.id=3
GROUP BY product.id;
通过运行此查询,我会收到与第一个,第二个或第三个标记相关的所有独特产品。
我想得到的是相同的结果集,但按此顺序:
我预感到可以通过组合多个联合和子查询来完成类似的结果,但我不确定如何做到这一点。
我真的希望有人可以帮助我完成这个项目或者给我一些关于这个主题的阅读材料。它有可能吗?
提前致谢!
答案 0 :(得分:3)
SELECT products.product_id AS product_id
, SUM(IF(tag2product.tag_id IN (1,2,3),1,0)) AS matched_tags
, COUNT(*) AS total_tags
FROM (SELECT DISTINCT product_id
FROM tag2product
WHERE tag_id IN (1,2,3)) AS products
JOIN tag2product
ON products.product_id = tag2product.product_id
GROUP BY product_id
ORDER BY matched_tags DESC, total_tags;
答案 1 :(得分:1)
首先,如果您对其他标记感兴趣,则需要将where
更改为having
子句。否则,您将不会获得order by
子句的信息。
您想要的查询只有一个相当复杂的order by
子句:
SELECT product.id
FROM product LEFT OUTER JOIN
tag2product
ON product.id=tag2product.product_id LEFT OUTER JOIN
tag ON tag2product.tag_id = tag.id
WHERE tag.id=1 OR tag.id=2 OR tag.id=3
GROUP BY product.id
HAVING sum(tag.id in (1, 2, 3)) > 0
order by (case when count(distinct case when tag.id in (1, 2, 3) then tag.id end) = 3 and
sum(tag.id not in (1, 2, 3)) = 0
then 1
when count(distinct case when tag.id in (1, 2, 3) then tag.id end) = 3
then 2
when count(distinct case when tag.id in (1, 2, 3) then tag.id end) = 2 and
sum(tag.id not in (1, 2, 3)) = 0
then 3
when count(distinct case when tag.id in (1, 2, 3) then tag.id end) = 2
then 4
when count(distinct case when tag.id in (1, 2, 3) then tag.id end) = 1 and
sum(tag.id not in (1, 2, 3)) = 0
then 5
when count(distinct case when tag.id in (1, 2, 3) then tag.id end) = 1
then 6
end)