在做去哪儿网数据分析时候被一个问题难倒了,之前通过scrapy将数据导入了MySQL,然后想分组查询MySQL数据库每个省份每个分组300条数据,但结果。。。
不明白结果怎么来的,头疼,等我成长为菜鸟+的时候估摸着就明白了,现在还是菜鸟-的状态。
相关子查询我会啊
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;
正确结果
有一点需要注意的是,三者运行时间有所差异,第一种方法运行速度比较快,连接方式查询明显慢一点。
最后,复习了一下基础查询方法
分类
- 按照子查询出现的位置
- select后面
仅仅支持标量子查询 - from后面
仅仅支持表子查询 - where或having后面
标量子查询
列子查询
行子查询 - exists后面(相关子查询)
表子查询
按照结果集的行列数不同
- 标量子查询(结果集只有一行一列)
- 列子查询(结果集只有一列多行)
- 行子查询(结果集有一行多列)
- 表子查询(结果集一般为多行多列)
网友评论