MySQL:按类别计数对项目进行排序

MySQL: Sort items by category count

我目前使用的查询非常有效:

SELECT * FROM `items` WHERE `id` IN 
    (SELECT `item_id` FROM `categories_items` 
     WHERE `category_id` IN (1, 2) GROUP BY `item_id` 
     HAVING COUNT(`item_id`) = 2);

它选择所有选定(复选框)类别中的所有项目。

问题是大多数项目都在很多类别中,少数项目只在两个类别中,当我只检查这两个类别时,我仍然得到一个包含数百个项目的列表,几乎不可能找到这些项目属于几类。

我的第一个想法是在查询中的某处添加一个 ORDER BY "number_of_total_categories_that_the_selected_item_is_in" ASC,但由于我什至得到了当前查询的帮助并且可能会有很多 calculations/subqueries 才能工作,我想到了 items table 中的一个额外列,用于保存它所在的类别数!

如果没有,我能想到的就是在需要时手动更新 items 中的 category_count 列。

编辑:Table field that holds row count from another table 看起来很有趣,但我不知道它是否适用于 MySQL。

您想使用 join 而不是 in。以下查询过滤器仅包含您想要的两个类别的项目。它还统计类别总数,可用于order by:

SELECT i.*
FROM `items` i JOIN
       (SELECT `item_id`, COUNT(*) as cnt
        FROM `categories_items` 
        WHERE `category_id` IN (1, 2)
        GROUP BY `item_id` 
        HAVING COUNT(DISTINCT CASE WHEN category_id IN (1, 2) THEN category_id END) = 2
       ) c
       ON i.id = c.item_id
ORDER BY cnt ASC;

编辑:

如果要计算 所有 个类别,则去掉 where。它并没有真正做任何事情:

SELECT i.*
FROM `items` i JOIN
       (SELECT `item_id`, COUNT(*) as cnt
        FROM `categories_items` 
        GROUP BY `item_id` 
        HAVING COUNT(DISTINCT CASE WHEN category_id IN (1, 2) THEN category_id END) = 2
       ) c
       ON i.id = c.item_id
ORDER BY cnt ASC;