首页 > 解决方案 > Mysql多列计数在列中具有最小出现值

问题描述

我有一个 t1 表,有 5 列和 80000 行:

+---+--------+-------+--------+------------+
|id |category|groupe |subject | description|
+---+--------+-------+--------+------------+
|1  |categ1  |group1 |subject1| desc1      |
|2  |categ1  |group2 |subject2| desc2      |
|3  |categ1  |group2 |subject5| desc3      |
|4  |categ2  |group1 |subject5| desc4      |
|5  |categ2  |group3 |subject1| desc5      |
|6  |categ2  |group3 |subject2| desc6      |
|7  |categ3  |group1 |subject1| desc7      |
|8  |categ3  |group1 |subject4| desc8      |
+---+--------+-------+--------+------------+

我需要提取在类别中至少出现 30 次值和 30 次组和 30 次主题的行。

这意味着如果“categ3”出现超过 30 次,我需要与组和主题相同的categ3 行。

但是当我使用下面的查询时,最终结果可能少于 30 个类别 3,因为结果已按组或主题过滤,删除了具有类别 3 的 id。

您可以在db<>fiddle上看到一个示例,出现 10 次的良好查询结果 count() 必须返回 118 行。

        select 
            *
        from 
            t1 
        where
            category in (
                SELECT
                    category
                FROM
                    t1
                GROUP BY
                    category
                HAVING
                    COUNT(category) >= 30
            )
            and 
            groupe in (
                SELECT
                    groupe
                FROM
                    t1
                GROUP BY
                    groupe
                HAVING
                    COUNT(groupe) >= 30
            )
            and 
            subject in (
                SELECT
                    subject
                FROM
                    t1
                GROUP BY
                    subject
                HAVING
                    COUNT(subject) >= 30
            )

此查询返回 ID 上的交集,其中 category、groupe 和 subject 在值上出现 30 次,但此交集会减少结果计数……这意味着某些类别值的计数可能会减少到小于 30 的数字。

对于简历,我需要在交集结果中出现 30 次。

我想我需要做一个递归过滤器并且必须重复循环直到输入行等于输出行..但我不知道该怎么做......一个想法?

谢谢

标签: mysql

解决方案


专业提示:在这种情况下,描述您的要求需要很多思考。正如您所想的那样,将 SQL 视为一组行的处理器。尽可能仔细地描述需求总是值得的,尤其是当它像这个一样棘手时。通常,描述问题域是有帮助的,而不仅仅是谈论列和值。

我猜您需要满足您的三个不同标准的行集(超过 x 个重复项)。您可以为这些行使用一组id值,因为它们显然是主键(唯一)。

这是一组 ID

    SELECT id FROM dataset WHERE category IN (
         SELECT category FROM dataset GROUP BY category HAVING COUNT(*) >= 5))

我相信您需要位于这三组交集的所有行。也就是说,您希望所有三个项目都频繁出现的任何行。你可以用

  id IN set1   AND   id IN set2  AND    id IN set3

如果您需要这些集合的并集,您可以使用它。这为您提供了三个项目中的任何一个经常重复出现的行。

  id IN set1   OR   id IN set2    OR    id IN set3

所以这里是查询

SELECT *
  FROM dataset 
 WHERE id IN (
      SELECT id FROM dataset WHERE category IN (
           SELECT category FROM dataset GROUP BY category HAVING COUNT(*) >= 5))
   AND id IN (
      SELECT id FROM dataset WHERE groupe IN (
           SELECT groupe FROM dataset GROUP BY groupe HAVING COUNT(*) >= 5))
   AND id IN (
      SELECT id FROM dataset WHERE subject IN (
           SELECT subject FROM dataset GROUP BY subject HAVING COUNT(*) >= 5))

我用于5重复阈值。您可以使用其他号码。

如果您希望结果集仅包含在结果集中而不是在数据集中包含至少十个项目的行,则可以使用此查询。

select d.* 
from dataset d
join (
select count(*), groupe, category, subject
  from dataset
 group by groupe, category, subject
 having count(*) >= 10
) e ON d.groupe=e.groupe AND d.category = e.category AND d.subject = e.subject

推荐阅读