SQL 总结(索引index、子查询、分页、开窗函数等)

索引index(相当于创建目录)

优点:提高查询效率。

缺点:占空间,并且添加、更新、删除数据的时候同步更新索引,会降低insert、update、delete的速度。在where上创建索引。

预读取:提前预测执行,然后在查询实际使用这些页时将在缓冲区高速缓存。

逻辑读取:从缓存中读取数据。

物理读取:从硬盘中读取数据。

打开:查询--查询选项--高级--勾上最后两个(如下所示)

 

--子查询:把查询出来的虚表(结果集)作为原始表,再次进行查询,如下,括号里面的就是子查询语句

select * from  (select * from stuInfo_new where java>80 or java<60)as s where gender='男';

--独立子查询:子查询语句可以单独执行的,就是独立子查询,如上,就是独立子查询。

--相关子查询: 子查询语句不可以单独执行,而是依靠外部查询条件一并执行的,就是相关子查询。

 

select MAX(english) from stuInfo_new union all

select min(english) from stuInfo_new union all

select avg(english) from stuInfo_new;

 

select (select MAX(english) from stuInfo_new),

(select MIN(english) from stuInfo_new),

(select avg(english) from stuInfo_new);

--子查询如果是多个结果,前面不能用=

select * from stuInfo_new where java in (60,70);

select * from stuInfo_new where stuInfo_new.id=test.id;

select * from stuInfo_new where exists(select * from test where stuInfo_new.id=test.id );

总结:=只能对应1个,你只能单行多列。

--(执行顺序)先执行外部的from 然后按照sql执行顺序执行到子查询语句的时候,子查询才执行

----------------------------分页------------------------

《一》--分页方式一:

-- 原理:子查询中查询出之前已经读过的所有数据,然后外部查询全表所有数据中不包含子查询中的数据,然后取前N(N是每页几条)条

-- 方式一是传统写法,现在已经过时了,现在都用方式二

select top(5) * from stuInfo_new;

select * from stuInfo_new order by java desc;

(任选3个写即可)

①--查询第1页的数据

select top(5) * from stuInfo_new where java not in (select top(5*(1-1)) java from stuInfo_new order by java desc) order by java desc;

②--查询第2页的数据

select top(5) * from stuInfo_new where java not in (select top(5*(2-1)) java from stuInfo_new order by java desc) order by java desc;

③--查询第3页的数据

select top(5) * from stuInfo_new where java not in (select top(5*(3-1)) java from stuInfo_new order by java desc) order by java desc;

select * from stuInfo_new order by id asc;

 

④--查询第7页数据

select * from stuInfo_new order by id;

select top(5) * from stuInfo_new where id not in (select top(5*(4-1)) id from stuInfo_new order by id desc) order by id desc;

 

⑤--查询最后一页的数据

select top(5) * from stuInfo_new where id not in (select top(5*(7-1)) id from stuInfo_new order by id) order by id;

 

 

----------------------------开窗函数-----------------------------

1、--聚合函数只能显示一行,需要显示所有行时用到开窗函数

select *,java平均分=AVG(java) over()  from stuInfo_new;

select gender ,AVG(java) over() from stuInfo_new ;

2、--需求:后面加一列,显示男女各自的java平均分

select *,java平均分=AVG(java) over(partition by gender) from stuInfo_new;

3、--row_number()函数:给每一行加序号,但是要告诉数据库,怎么加行号,按什么顺序加,所以用到了开窗函数over(),并且通过over()告诉row_number()按什么列排序

select *,行号=ROW_NUMBER() over(order by java) from stuInfo_new;

--有了序号之后,分页就更简单了

4、--查第2页

select * from stuInfo_new  where id between (5*(2-1)+1) and (5*2)  order by id;

5、--查第3页

select * from stuInfo_new  where id between (5*(3-1)+1) and (5*3)  order by id;

6、--查第4页

select * from stuInfo_new  where id between (5*(4-1)+1) and (5*4)  order by id;

delete from stuInfo_new where name like '高帅';

7、--这个案例告诉我们:按照序号来查,很方便,思路也很清晰,但是我们是把id当成序号了,而id不可靠,它有可能没有严格的按照一定的顺序来,有可能少了或者多了,或者跳了好几步,那怎么解决呢?就需要我们自己加一列百分之百可靠的序号(简单来说查询时id不严谨,为了解决id缺增问题,需加一列可靠的序号--引用ROW_NUMBER()

select *,序号=ROW_NUMBER() over(order by english desc) from stuInfo_new;

 

《二》--分页方式二:

原理:给原表加一个个序号列,这个序号列是稳定可靠的,不会漏,也不会多,也不会跳,然后把这个加完列的虚表作为原表被外部语句查询就行了(首先给原表加可靠的序号列,然后把加完列的虚表作为原表被外部语句查询)

1、-- 外部语句如何查询呢?就是用between and来选择你要查的页的开始行和结束行就行了

2、--需求,按照方式二来查询第5页数据

select * from (select *,序号=ROW_NUMBER() over(order by java desc) from stuInfo_new) as t where t.序号 between (5*(5-1)+1) and (5*5) order by t.序号;

3、--需求:按照方式一来查询第7页的数据

select top(5) * from stuInfo_new where id not in (select top(5*(7-1)) id from stuInfo_new order by id) order by id;

4、--需求:按照方式一来查询第2页的数据

select top(5) * from stuInfo_new where java not in (select top(5*(2-1)) java from stuInfo_new order by java) order by java ;

select * from stuInfo_new order by java;

update stuInfo_new set java=96 where name like '张梦%';

delete from stuInfo_new where name like '刘书%';

insert into stuInfo_new values('20160505','41108219956565363','伍子胥','男',40,100,0,'1990-4-3','13536669999','楚国');

5、--需求:取第3页的数据,每页10条 , 要求用第二种方式。

select * from stuInfo_new order by id;

select * from (select *,序号=ROW_NUMBER() over(order by id) from stuInfo_new) as haha where haha.序号 between (10*(3-1)+1) and (10*3) order by haha.序号;

6、--分页注意:我们学了两种方式,第一种已经过时了,并且有漏洞(当外部查询not in子查询的时候,可能会出现漏数据的情况),是不严谨建议第二种。但是再注意:这两种方式都是sqlserver中的,而mysql和oracle数据库用的都不是这两种方式,但是原理相通,而且更简单,特别是mysql,一步搞定(select * from 表名 limit(10*(3-1)+7))

 

7、--需求:后面加一列,显示男女各自的java平均分  

①--解决方法:在开窗函数里面分组,而不是在后面用group by 分组,记住一句话就可以了,一旦用刀over(),就不要用group by,而是用partition by

select *,男女各自平均分=AVG(java) over(partition by gender) from stuInfo_new;

②--不允许使用开窗函数,实现上面需求

select * from stuInfo_new as t1 inner join (select gender,AVG(java) as java平均分 from stuInfo_new group by gender) as t2 on t1.gender=t2.gender;

select * from stuInfo_new t1 ,(select gender,AVG(java) as java平均分 from stuInfo_new group by gender) as t2 where t1.gender=t2.gender;

 

 

 

你可能感兴趣的:(数据库)