MySQL多列计数列中出现次数最少的值

时间:2019-01-22 14:00:14

标签: 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个categ3,因为结果已按删除具有categ3的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次。

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

谢谢

2 个答案:

答案 0 :(得分:1)

专业提示:在这种情况下,描述您的需求需要很多考虑。在考虑时,将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

所以here's the query

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

答案 1 :(得分:1)

在3列分组的同时添加一些DISTINCT。

select *
from dataset t
where t.category in (SELECT distinct category FROM dataset GROUP BY category, groupe, subject HAVING COUNT(*) >= 30)
and t.groupe in (SELECT distinct groupe FROM dataset GROUP BY category, groupe, subject HAVING COUNT(*) >= 30) 
and t.subject in (SELECT distinct subject FROM dataset GROUP BY category, groupe, subject HAVING COUNT(*) >= 30) 

db <>小提琴here

的测试

为参考起见,此查询将只选择出现tupple的次数超过30次的查询。
自然会比上面的查询少。

SELECT * 
FROM dataset 
WHERE (category, groupe, subject) IN (
    SELECT category, groupe, subject
    FROM dataset 
    GROUP BY category, groupe, subject
    HAVING COUNT(*) >= 30
)