MySQL通过占有而不是拥有某个功能进行排序

时间:2013-12-18 21:23:26

标签: mysql sql database

我一直在尝试创建一个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;

通过运行此查询,我会收到与第一个,第二个或第三个标记相关的所有独特产品。

我想得到的是相同的结果集,但按此顺序:

  1. 标有全部 1,2和3且没有其他产品的产品。
  2. 标有所有 1,2和3,的产品还有其他标签(可选择按其他标签的内部排序)。
  3. 标有任意两个 1,2和3个属性但没有其他属性的产品。
  4. 标有任意两个 1,2和3个属性的产品还有其他标记(此处的可选条件也适用于此处)< / LI>
  5. 使用 1,2或3个属性标记的产品,并且没有任何其他标记。
  6. 标有 1,2或3个属性 的产品有其他标签(与2和4相同)。
  7. 我预感到可以通过组合多个联合和子查询来完成类似的结果,但我不确定如何做到这一点。

    我真的希望有人可以帮助我完成这个项目或者给我一些关于这个主题的阅读材料。它有可能吗?

    提前致谢!

2 个答案:

答案 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)