美文网首页程序员
MySQL查询分组后前10条数据

MySQL查询分组后前10条数据

作者: 明日孤风寒 | 来源:发表于2019-10-02 19:26 被阅读0次

    在做去哪儿网数据分析时候被一个问题难倒了,之前通过scrapy将数据导入了MySQL,然后想分组查询MySQL数据库每个省份每个分组300条数据,但结果。。。

    由此,机智的我打开了Google和百度,在广大网友的支持下,姑且找到了解决问题的办法。但有个问题还是没有解决,查询后返回结果数目不等。最后结果是这样的 运行结果
    不明白结果怎么来的,头疼,等我成长为菜鸟+的时候估摸着就明白了,现在还是菜鸟-的状态。

    相关子查询我会啊

    SELECT m1.city,m1.title
    FROM message m1
    LEFT JOIN message m2
    ON m1.`city`=m2.`city`
    GROUP BY m1.`city`
    ORDER BY m1.`city`;
    

    结果返回了32条数据


    返回数据

    羊毛出在了羊身上,原因在于用group by查询数据时,会将数据分组合并,然后数据就成了32条了,也就是32个省市自治区(台湾也有)。
    然后我又来了一次

    SELECT city,title
    FROM (SELECT *
    FROM message
    ORDER BY city) m;
    
    返回结果

    貌似成功了,但从哪儿分组呢,分组体现在哪儿呢,加不进去啊???

    于是乎,求助万能的百度,得到了如下结果:

    第一个就是相关子查询了

    关联子查询会引用外部查询中的一列或多列。这种子查询之所以被称为关联子查询,是因为子查询的确与外部查询有关。当问题的答案需要依赖于外部查询中包含的每一行中的值时,通常就需要使用关联子查询。

    然后得到了如下结果

    • 非相关子查询是独立于外部查询的子查询,子查询总共执行一次,执行完毕后将值传递给外部查询,并且它是优先于外部查询先执行的,他执行了再执行外部。
    • 相关子查询的执行依赖于外部查询的数据,外部查询执行一行,子查询就执行一次。并且是外部先查询一次,然后再执行一次内部查询!

    执行过程如下

    • 从外层数据中取出一条数据,传递给内层数据查询
    • 内层查询操作得到相应的值
    • 外查询根据内查询的相关结果或结果集得到相应的行(满足一定条件)
    • 然后重复操作,直到完成任务

    然后大致懂得了操作

    SELECT m1.city,m1.title
    FROM message m1
    WHERE 10>(
        SELECT COUNT(1)
        FROM message m2
        WHERE m1.`id`>m2.`id` AND m1.`city`=m2.`city`
        )
    ORDER BY m1.city,m1.title;
    
    正确结果

    这个结果我猜想是这么运行的:
    首先了解MySQL语句执行顺序,这个至关重要

    Where -> Group By -> Having -> Order by

    这条语句中,父查询传入语句到子查询中,count语句查询出当前子查询语句中查询到的行,如果父查询的所有数值(id)都比他大,那这条语句(行)处于第一位,返回结果为1。同理,进行多次查询,得到另一个条件(city)相同前提下中每个元素所处位置。事情这样就简单了,父查询select一下再加入筛选条件即可得到正确结果。
    另外,这个语句还可以通过连接方式查询

    SELECT m1.city,m1.title
    FROM message m1
    LEFT JOIN message m2
    ON m1.`id` >m2.`id`AND m1.`city`=m2.`city`
    GROUP BY m2.`city`,m2.id
    HAVING COUNT(*)<=10
    ORDER BY m1.city;
    

    这样跑起来也是正确的


    正确结果

    内连接也是可以的

    SELECT m1.city,m1.title
    FROM message m1
    INNER JOIN message m2
    ON m1.`id` >= m2.`id`AND m1.`city`=m2.`city`
    GROUP BY m2.`city`,m2.id
    HAVING COUNT(*)<=10
    ORDER BY m1.city;
    
    正确结果

    有一点需要注意的是,三者运行时间有所差异,第一种方法运行速度比较快,连接方式查询明显慢一点。

    最后,复习了一下基础查询方法

    分类

    1. 按照子查询出现的位置
    • select后面
      仅仅支持标量子查询
    • from后面
      仅仅支持表子查询
    • where或having后面
      标量子查询
      列子查询
      行子查询
    • exists后面(相关子查询)
      表子查询

    按照结果集的行列数不同

    • 标量子查询(结果集只有一行一列)
    • 列子查询(结果集只有一列多行)
    • 行子查询(结果集有一行多列)
    • 表子查询(结果集一般为多行多列)

    相关文章

      网友评论

        本文标题:MySQL查询分组后前10条数据

        本文链接:https://www.haomeiwen.com/subject/zhtrpctx.html