这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。
而UNION ALL只是简单的将两个结果合并后就返回。这样,如果返回的两个结果集中有重复的数据,那么返回的结果集就会包含重复的数据了。
从效率上说,UNION ALL 要比UNION快很多,所以,如果可以确认合并的两个结果集中不包含重复的数据的话,那么就使用UNION ALL, 3.分页语句
取出sql表中第31到40的记录(以自动增长ID为主键) sql server方案1:
select top 10 * from t where id not in (select top 30 id from t order by id ) orde by id sql server方案2:
select top 10 * from t where id in (select top 40 id from t order by id) order by id desc
mysql方案:select * from t order by id limit 30,10
oracle方案:select * from (select rownum r,* from t where r<=40) where r>30
--------------------待整理进去的内容------------------------------------- pageSize=20; pageNo = 5;
1.分页技术1(直接利用sql语句进行分页,效率最高和最推荐的)
mysql:sql = \oracle: sql = \
\ \
\
\
注释:第7行保证rownum的顺序是确定的,因为oracle的索引会造成rownum返回不同的值
简洋提示:没有order by时,rownum按顺序输出,一旦有了order by,rownum不按顺序输出了,这说明rownum是排序前的编号。如果对order by从句中的字段建立了索引,那么,rownum也是按顺序输出的,因为这时候生成原始的查询结果集时会参照索引表的顺序来构建。
sqlserver:sql = \top 10 * from id not id(select top \+ (pageNo-1)*pageSize + \from articles)\
DataSource ds = new InitialContext().lookup(jndiurl); Connection cn = ds.getConnection();
//\ --->binary directive PreparedStatement pstmt = cn.prepareSatement(sql); ResultSet rs = pstmt.executeQuery()
while(rs.next())
{ out.println(rs.getString(1)); }
2.不可滚动的游标 pageSize=20; pageNo = 5; cn = null stmt = null; rs = null; try
{
sqlserver:sql = \ * from articles\
DataSource ds = new InitialContext().lookup(jndiurl); Connection cn = ds.getConnection();
//\ --->binary directive PreparedStatement pstmt = cn.prepareSatement(sql); ResultSet rs = pstmt.executeQuery() for(int j=0;j<(pageNo-1)*pageSize;j++) { }
rs.next();
int i=0;
while(rs.next() && i<10) { i++; }
out.println(rs.getString(1));
}
cacth(){} finnaly { }
3.可滚动的游标 pageSize=20; pageNo = 5;
if(rs!=null)try{rs.close();}catch(Exception e){} if(stm......... if(cn............
cn = null stmt = null; rs = null; try {
sqlserver:sql = \ * from articles\
DataSource ds = new InitialContext().lookup(jndiurl); Connection cn = ds.getConnection();
//\ --->binary directive
PreparedStatement pstmt = cn.prepareSatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,...);
//根据上面这行代码的异常SQLFeatureNotSupportedException,就可判断驱动是否支持可滚动游标
ResultSet rs = pstmt.executeQuery() rs.absolute((pageNo-1)*pageSize) int i=0;
while(rs.next() && i<10) {
i++;
out.println(rs.getString(1)); } }
cacth(){} finnaly {
if(rs!=null)try{rs.close();}catch(Exception e){} if(stm......... if(cn............
}
3.用一条SQL语句 查询出每门课都大于80分的学生姓名 name kecheng fenshu 张三 语文 81 张三 数学 75 李四 语文 76 李四 数学 90 王五 语文 81 王五 数学 100 王五 英语 90
准备数据的sql代码:
create table score(id int primary key auto_increment,name varchar(20),subject varchar(20),score int);
insert into score values (null,'张三','语文',81), (null,'张三','数学',75), (null,'李四','语文',76), (null,'李四','数学',90), (null,'王五','语文',81), (null,'王五','数学',100),
(null,'王五 ','英语',90);
提示:当百思不得其解时,请理想思维,把小变成大做,把大变成小做,
答案:
A: select distinct name from score where name not in (select distinct name from score where score<=80)
B:select distince name t1 from score where 80< all (select score from score where name=t1);
4.所有部门之间的比赛组合
一个叫department的表,里面只有一个字段name,一共有4条纪录,分别是a,b,c,d,对应四个球对,现在四个球对进行比赛,用一条sql语句显示所有可能的比赛组合.
答:select a.name, b.name
from team a, team b where a.name < b.name
4.每个月份的发生额都比101科目多的科目 请用SQL语句实现:从TestDB数据表中查询出所有月份的发生额都比101科目相应月份的发生额高的科目。请注意:TestDB中有很多科目,都有1-12月份的发生额。 AccID:科目代码,Occmonth:发生额月份,DebitOccur:发生额。 数据库名:JcyAudit,数据集:Select * from TestDB 准备数据的sql代码: drop table if exists TestDB;
create table TestDB(id int primary key auto_increment,AccID varchar(20), Occmonth date, DebitOccur bigint); insert into TestDB values (null,'101','1988-1-1',100), (null,'101','1988-2-1',110), (null,'101','1988-3-1',120), (null,'101','1988-4-1',100), (null,'101','1988-5-1',100), (null,'101','1988-6-1',100),
(null,'101','1988-7-1',100), (null,'101','1988-8-1',100);
--复制上面的数据,故意把第一个月份的发生额数字改小一点
insert into TestDB values (null,'102','1988-1-1',90), (null,'102','1988-2-1',110), (null,'102','1988-3-1',120), (null,'102','1988-4-1',100), (null,'102','1988-5-1',100), (null,'102','1988-6-1',100),
(null,'102','1988-7-1',100), (null,'102','1988-8-1',100);
--复制最上面的数据,故意把所有发生额数字改大一点 insert into TestDB values (null,'103','1988-1-1',150), (null,'103','1988-2-1',160), (null,'103','1988-3-1',180), (null,'103','1988-4-1',120), (null,'103','1988-5-1',120),
(null,'103','1988-6-1',120), (null,'103','1988-7-1',120), (null,'103','1988-8-1',120);
--复制最上面的数据,故意把所有发生额数字改大一点 insert into TestDB values (null,'104','1988-1-1',130), (null,'104','1988-2-1',130), (null,'104','1988-3-1',140), (null,'104','1988-4-1',150), (null,'104','1988-5-1',160), (null,'104','1988-6-1',170),
(null,'104','1988-7-1',180), (null,'104','1988-8-1',140);
--复制最上面的数据,故意把第二个月份的发生额数字改小一点 insert into TestDB values (null,'105','1988-1-1',100), (null,'105','1988-2-1',80), (null,'105','1988-3-1',120), (null,'105','1988-4-1',100), (null,'105','1988-5-1',100), (null,'105','1988-6-1',100), (null,'105','1988-7-1',100), (null,'105','1988-8-1',100); 答案:
select distinct AccID from TestDB
where AccID not in (select TestDB.AccIDfrom TestDB, (select * from TestDB where AccID='101') as db101