sql进阶:select语句究竟发生了啥,巩固编写复杂sql的基础

1.准备工作

准备了两张表,用于测试

-- ----------------------------
-- Table structure for info
-- ----------------------------
DROP TABLE IF EXISTS `info`;
CREATE TABLE `info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `views` int(255) DEFAULT NULL,
  `info_type_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

-- ----------------------------
-- Table structure for info_type
-- ----------------------------
DROP TABLE IF EXISTS `info_type`;
CREATE TABLE `info_type` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

将上面的sql导入navicat

info表

info_type表

2.select语句发生了什么?

现在我要查询info表所有的数据,很容易写出如下sql

SELECT * FROM info;

不知道大家想过没有,select的时候究竟发生了什么?

其实sql语句执行的时候,如果看到select,就会根据from后面的表名,一条一条的查询,最终合并到结果集中。

如果我们再加一个where条件,那么就会进行筛查。

注意,这个筛查会发生在每一条语句上。

比如,当你执行SELECT * from info where info_type_id = 2;这条语句,0.001ms的时候是查询这条数据

请问,他符合where条件吗?不符合吧,那么这一条就过滤掉,继续下一条。

最终,不符合条件的都被过滤,那些符合条件的才被筛出来了。

3.复杂查询

下面介绍一个比较考验思维的sql,非常适合复习我们已有的sql知识。

对于某些复杂的需求,sql的编写难度会加大。

比如,现在我要求查询info_type_id=3,并且浏览量最高的两条数据,考虑下怎么写?

先看下info_type_id=3的所有数据

SELECT * from info where info_type_id = 3;

浏览量最高的两条数据,很容易想到对views进行倒叙排序,然后取前两条。

SELECT * from info where info_type_id = 3 ORDER BY views desc;

那么,怎么取前两条呢?直接分页即可。

SELECT * from info where info_type_id = 3 ORDER BY views desc LIMIT 0,2;

那假如我要用一条sql获取每个类别浏览量最高的前两条呢?

相信很多人第一反应是用group by 去分组,但是似乎比较困难。

其实,我们只要牢记select的原理是一条一条去扫描匹配的,就不难。

比如,我们扫描到第一条:

思考,该怎么去判断这一条的views(浏览量)是该类型(info_type_id=3)前两位呢?

是不是只需要让这张表中info_type_id=3(条件1)并且views大于这条数据的views(条件2),然后再要求这样的数据<=1条(条件3)就行了呢?

说说为什么要求这样的数据<=1条?

如果等于1,说明只有一条比当前这条views大,加上这一条,就是views最高的两条,符合条件。

如果小于1,说明没有任何一条比当前这条views大,那么当前这条就是views最高的那条,符合条件。

于是,针对info_type_id=3的情况,得到sql

select t1.* from info t1 where  t1.info_type_id = 3
		and (select count(1) from info t2  where  t2.info_type_id = 3 and t2.views > t1.views ) <= 1

成功了,然后再改写成全部的情况:

SELECT t1.* from info t1
where (
	select count(1) from info t2  where  t2.info_type_id = t1.info_type_id 
		and t2.views > t1.views ) <= 1
order by info_type_id;

总之,我们要牢记一点,select的时候,是一条条去执行的,where条件就是对每一条的过滤。这样的复杂sql也就不难理解了。

 我是兔哥,关注我,学习编程不迷路~~

猜你喜欢

转载自blog.csdn.net/weixin_39570751/article/details/124111515
今日推荐