SQL点滴25—T-SQL面试语句,练练手
1. 用一条SQL语句查询出每门课都大于80分的学生姓名
name kecheng fenshu
张三 语文 81
张三 数学 75
李四 语文 76
李四 数学 90
王五 语文 81
王五 数学 100
王五 英语 90
思路:这里不能直接用分数>80这样的比较条件来查询的到结果,因为要求没门成绩都大于80。我们可以反过来思考,如果有一门成绩小于80,那么就不符合要求。先找出成绩表中成绩<80的多有学生姓名,不能重复,然后再用not in找出不再这个集合中的学生姓名。
create table #成绩(姓名varchar(20),课程名称varchar(20),分数int)
insert into #成绩values
('张三', '语文', 81),
('张三', '数学', 75),
('李四', '语文', 76),
('李四', '数学', 90),
('王五', '语文', 81),
('王五', '数学', 100),
('王五', '英语', 90)
select distinct(姓名) from #成绩 where 姓名 not in(select distinct(姓名) from #成绩 where 分数<=80)
经luofer提示还有一种思路,是用group by + hvaing,这绝对是一种好方法。我估计出这个题的人就是要考察这个知识,代码如下:
select 姓名 from #成绩
group by 姓名
having min(分数)>80
还有一种方法类似于第一种
select distinct a.姓名 from #成绩 a where not exists (select 1 from #成绩 where 分数<80 and 姓名=a.姓名)
2. 学生表如下:
自动编号 学号 姓名 课程编号 课程名称 分数
1 2005001 张三 0001 数学 69
2 2005002 李四 0001 数学 89
3 2005001 张三 0001 数学 69
删除除了自动编号不同,其他都相同的学生冗余信息
思路:这个和上面的一样,也不能直接删除,而是要先找出自动编号不相同,其他都相同的行,这个要使用group by语句,并且将其他的字段都放在group by后面,这样找出来的行都是没有冗余的行,然后随便保留其中一个自动编号,删除其他的行。
create table #成绩(自动编号 int, 学号 int,姓名 varchar(20),课程编号 int,课程名称 varchar(20),分数 int)
insert into #成绩 values
(1,2005001 ,'张三', 1, '语文', 81),
(2,2005001 ,'李四', 1, '语文', 81),
(3,2005001 ,'张三', 1, '语文', 81),
(4,2005001 ,'张三', 1, '语文', 81)
select * from #成绩
drop table #成绩
delete from #成绩 where 自动编号 not in
(select MIN(自动编号) from #成绩 group by 学号,姓名,课程编号,课程名称,分数)
经广岛之恋的提醒发现另外一种思路,代码如下:
delete from #成绩 where 自动编号 not in
(select distinct(a.自动编号) from #成绩 a join #成绩 b on a.自动编号>b.自动编号
where a.学号=b.学号 and a.姓名=b.姓名 and a.课程编号=b.课程编号 and a.分数=b.分数)
如果不考虑自动编号,还可以这样
--注意identity用法,只能用在有into的select语句中
select identity(int,1,1) as id, 学号,姓名,课程编号,课程名称,分数
into #temp
from #成绩 group by 学号,姓名,课程编号,课程名称,分数
truncate table #成绩
insert into #成绩 select * from #temp
3. 一个叫department的表,里面只有一个字段name,一共有4条纪录,分别是a,b,c,d,对应四个球对,现在四个球对进行比赛,用一条sql语句显示所有可能的比赛组合。
思路:这是一个组合问题,就是说四个不同的元素有多少种不同的两两组合。现在要把这个问题用sql语句实现。既然这四个元素是不相同的,我们可以将这个表当成两个集合,求他们的笛卡尔积,然后再从笛卡尔积中找到那些元素不相同的,并且不重复的组合。
create table #department(taname char(1))
insert into #department values
('a'),('b'),('c'),('d')
--下面两条语句都可以,多谢wanglinglong提醒
select a.taname,b.taname from #department a,#department b where a.taname < b.taname
select a.taname,b.taname from #department a,#department b where a.taname > b.taname
4.怎么把这样一个表
year month amount
1991 1 1.1
1991 2 1.2
1991 3 1.3
1991 4 1.4
1992 1 2.1
1992 2 2.2
1992 3 2.3
1992 4 2.4
查成这样一个结果
year m1 m2 m3 m4
1991 1.1 1.2 1.3 1.4
1992 2.1 2.2 2.3 2.4
思路:这个很明显是一个行列转换,首先会想到pivot。结果中有m1,m2,m3,m4四个新的列,他们需要从原来的行中转换。
create table #sales(years int,months int,amount float)
insert into #sales values
(1991, 1, 1.1),
(1991, 2, 1.2),
(1991, 3, 1.3),
(1991, 4, 1.4),
(1992, 1, 2.1),
(1992, 2, 2.2),
(1992, 3, 2.3),
(1992, 4, 2.4)
select pt.years,[] as m1,[] as m2,[] as m3,[] as m4
from (select sod.amount,sod.months,sod.years as years from #sales sod) so
pivot
(min(so.amount) for so.months in ([], [],[],[])) as pt
注意[1],[2],[3],[4]中括号不可缺少,否则会出错。还有一种写法是使用子查询,这个要新建4个子查询进而得到新的列:
select a.years,
(select m.amount from #sales m where months=1 and m.years=a.years) as m1,
(select m.amount from #sales m where months=2 and m.years=a.years) as m2,
(select m.amount from #sales m where months=3 and m.years=a.years) as m3,
(select m.amount from #sales m where months=4 and m.years=a.years) as m4
from #sales a group by a.years
还可以这样写,大同小异:
select a.years,
sum(case months when 1 then amount else 0 end) as m1,
sum(case months when 2 then amount else 0 end) as m2,
sum(case months when 3 then amount else 0 end) as m3,
sum(case months when 4 then amount else 0 end) as m4
from #sales a group by a.years
5.有两个表A和B,均有key和value两个字段,如果B的key在A中也有,就把B的value换为A中对应的value。这道题的SQL语句怎么写?
思路:这个问题看似简单,只要一个update语句,然后找到相同的key,更新value字段就可以了。可能你首先会写成这样:update #b set #b.value=(select #a.value from #a where #a.keys=#b.keys)。但是要注意的是如果仅仅找相同的key会有很多匹配,更新的时候会出现错误,所以要在外层限制。
create table #a(keys int , value varchar(10))
insert into #a values
(1,'aa'),
(2,'ab'),
(3,'ac')
create table #b(keys int , value varchar(10))
insert into #b values
(1,'aa'),
(2,'a'),
(3,'a')
update #b set #b.value=(select #a.value from #a where #a.keys=#b.keys) where #b.keys in
(select #b.keys from #b,#a where #a.keys=#b.keys and #a.value<>#b.value)
在luofer的提醒之,有了第二个思路
update #b set #b.value=s.value
from (select * from #a except select * from #b) s where s.keys=#b.keys
luofer是牛人啊!
再举一个例子,已知有一个课程表PressErp..Course,里面已经有一些数据,现在要向教师表[Press].[dbo].[Teacher]中添加新数据,但是有的老师课程可能不在这个已知的课程表中,这时候就可以用到这个except了,它的作用就是向这个课程表中添加以前不存在的课程名称。注意关键字distinct和except。
insert into Course select distinct(课程) from [Press].[dbo].[Teacher] a except select b.CourseName from Course b
6. 两张关联表,删除主表中已经在副表中没有的信息。
思路:这个就是存在关系,可以使用in,也可以使用exists。
create table #zhubiao(id int,name varchar(5))
insert into #zhubiao values
(1,'aa'),
(2,'ab'),
(3,'ac')
create table #fubiao(id int, grade varchar(5))
insert into #fubiao values
(1,'aa'),
(2,'ab')
delete from #zhubiao where id not in(select b.id from #fubiao b)
delete from #zhubiao where not exists(select 1 from #fubiao where #zhubiao.id=#fubiao.id)
7. 原表:
courseid coursename score
1 java 70
2 oracle 90
3 xml 40
4 jsp 30
5 servlet 80
为了便于阅读,查询此表后的结果显式如下(及格分数为60):
courseid coursename score mark
1 java 70 pass
2 oracle 90 pass
3 xml 40 fail
4 jsp 30 fail
5 servlet 80 pass
思路:这个就很直接了,使用case语句判断一下。
create table #scores(course int,coursename varchar(10),score int)
insert into #scores values
(1, 'java', 70 ),
(2, 'oracle', 90),
(3, 'xmls', 40),
(4, 'jsp', 30),
(5, 'servlet', 80 )
select course,coursename,
case when score>60 then 'pass' else 'fail' end as mark
from #scores
8. 原表:
id proid proname
1 1 M
1 2 F
2 1 N
2 2 G
3 1 B
3 2 A
查询后的表:
id pro1 pro2
1 M F
2 N G
3 B A
思路:依旧是行列转换,这个在面试中的几率很高。这个语句还是有两种写法,如下:
create table #table1(id int,proid int,proname char)
insert into #table1 values
(1, 1, 'M'),
(1, 2, 'F'),
(2, 1, 'N'),
(2, 2, 'G'),
(3, 1, 'B'),
(3, 2, 'A')
select id,
(select proname from #table1 where proid=1 and id=b.id) as pro1,
(select proname from #table1 where proid=2 and id=b.id) as pro2
from #table1 b group by id
select d.id,[] as pro1,[] as pro2 from
(select b.id,b.proid,b.proname from #table1 b) as c
pivot
(min(c.proname) for c.proid in([],[])) as d
9. 如下
表a
列 a1 a2
记录 1 a
1 b
2 x
2 y
2 z
用select能选成以下结果吗?
1 ab
2 xyz
思路:这个开始想使用行列转换来写,没有成功,后来没有办法只好用游标,代码如下:
create table #table2(id int , value varchar(10))
insert into #table2 values
(1,'a'),
(1,'b'),
(2,'x'),
(2,'y'),
(2,'z')
create table #table3(id int,value varchar(100) );insert into #table3(id,value) select distinct(id),'' from #table2
declare @id int,@name varchar(10)
declare mycursor cursor for select * from #table2
open mycursor
fetch next from mycursor into @id,@name
while (@@Fetch_Status = 0)
begin
update #table3 set value=value+@name where id=@id
fetch next from mycursor into @id,@name
end
close mycursor
deallocate mycursor
select * from #table3
有两个要注意的地方,
a.#table3里面的value字段初始值如果不设置的话默认是null,后面更新的时候null+'a'任然是null,最后得到的value永远是null。所以默认是''
b.第二个fetch语句一定要放在begin和end之间,要不然会死循环的,不常用的语句写起来很不爽快
经 scottshen提醒,使用for xml更加的简单,看下面的语句:
SELECT id,
(SELECT value + '' FROM #table2 WHERE id=a.id FOR XML PATH('')) AS [values]
FROM #table2 AS a GROUP BY a.id
--或者这样写
select distinct a.id,
(select b.value+'' from #table2 b where b.id=a.id for XML path('')) as value
from #table2 a
下面这一句帮助我们理解for xml的工作原理
select ''+a.value from #table2 a where id=2 for xml path('')
10.一个业务有多个访谈信息,要求每次添加访谈信息的时候都要更新业务中的当前添加的访谈信息的ID,这样可以快速查找当前业务的最新状态。
update MaintainMessage set CurrentCommunicateID=(select MAX(a.ID) from Communicate a where a.MaintainId=MaintainMessage.ID)
注意MaintainMessage.ID中的MaintainMessage不能省略。
SQL点滴25—T-SQL面试语句,练练手的更多相关文章
- SQL点滴26—常见T-SQL面试解析
原文:SQL点滴26-常见T-SQL面试解析 它山之石可以攻玉,这一篇是读别人的博客后写下的,不是原原本本的转载,加入了自己的分析过程和演练.sql语句可以解决很多的复杂业务,避免过多的项目代码,下面 ...
- SQL点滴2—重温sql语句中的join操作
原文:SQL点滴2-重温sql语句中的join操作 1.join语句 Sql join语句用来合并两个或多个表中的记录.ANSI标准SQL语句中有四种JOIN:INNER,OUTER,LEFTER,R ...
- SQL点滴1—SET QUOTED_IDENTIFIER OFF语句的作用
原文:SQL点滴1-SET QUOTED_IDENTIFIER OFF语句的作用 先看下面几个sql语句 代码 SELECT * FROM [USER] WHERE a= 'netasp' ...
- SQL点滴15—在SQL Server 2008中调用C#程序
原文:SQL点滴15-在SQL Server 2008中调用C#程序 T-SQL的在执行普通的查询的时候是很高效的,但是在执行循环,判断这样的语句的时候效率就不那么的高了.这时可以借助CLR了,我们可 ...
- SQL点滴7—使用SQL Server的attach功能出现错误及解决方法
原文:SQL点滴7-使用SQL Server的attach功能出现错误及解决方法 今天用SQL Server 2008的attach功能附加一个数据库,出了点问题,提示的错误是: Unable to ...
- Azure SQL Database (25) Azure SQL Database创建只读用户
<Windows Azure Platform 系列文章目录> 本文将介绍如何在Azure SQL Database创建只读用户. 请先按照笔者之前的文章:Azure SQL Databa ...
- SQL点滴17—使用数据库引擎存储过程,系统视图查询,DBA,BI开发人员必备基础知识
原文:SQL点滴17-使用数据库引擎存储过程,系统视图查询,DBA,BI开发人员必备基础知识 在开发过程中会遇到需要弄清楚这个数据库什么时候建的,这个数据库中有多少表,这个存储过程长的什么样子等等信息 ...
- SQL点滴35—SQL语句中的exists
原文:SQL点滴35-SQL语句中的exists 比如在Northwind数据库中有一个查询为 SELECT c.CustomerId,CompanyName FROM Customers c WHE ...
- SQL点滴32—Excel中CONCATENATE函数生成SQL语句
原文:SQL点滴32-Excel中CONCATENATE函数生成SQL语句 当拿到一个Excel的时候需要将这里面的数据插入到数据库里面,该怎么办,除了使用SSIS数据导入之外还可以使用Excel中的 ...
随机推荐
- Codefoces 432 C. Prime Swaps
哥德巴赫猜想: 任一大于2的偶数,都可表示成两个素数之和. 任一大于5的整数都可写成三个质数之和. 贪心取尽可能大的素数..... C. Prime Swaps time limit per test ...
- Eclipse SDK构建J2EE开发环境
鄙视官Java EE Developers 体积庞大的兄弟们可以提出自己的J2EE开发环境! 1.第一次去Eclipse官网下载Eclipse IDE 我使用的是:Eclipse IDE for Ja ...
- [Erlang危机](4.5)第四章练习
原创文章.转载请注明出处:server非业余研究http://blog.csdn.net/erlib 作者Sunface 联系邮箱:cto@188.com Exercises 练习 Review Qu ...
- 先锋军Android注射技术《三》
继续 于<两>通过专门出台ptrace实施注射的技术解决方案,在这一章,我就为大家介绍一Android在独特的喷射技术,我点了他的名字--Component Injection.顾名思义. ...
- C#开发中使用配置文件
C#开发中使用配置文件对象简化配置的本地保存 0x00 起因 程序的核心是数据和逻辑,开发过程中免不了要对操作的数据进行设置,而有些数据在程序执行过程中被用户或程序做出的修改是应该保存下来的,这样程序 ...
- Linux服务器杀马(转)
开篇前言 Linux服务器一直给我们的印象是安全.稳定.可靠,性能卓越.由于一来Linux本身的安全机制,Linux上的病毒.木马较少,二则由于宣称Linux是最安全的操作系统,导致很多人对Linux ...
- php用空格代替标点符号
php作为常规赛的符号替换为空格 <? php $character = "!@#$%^&*于'纸'纸'文().,<>|[]'\":;}{-_+=? /a ...
- mysql JDBC总结
今天复习了下jdbc操作数据库,其实通过复习,感觉对类的熟悉和方法的运用都是小事,毕竟有API都可以查得到. 关键是一些设计, 1. 比如: Class.forName("");这 ...
- SQL Server编程系列(2):SMO常用对象的有关操作
原文:SQL Server编程系列(2):SMO常用对象的有关操作 在上一篇周公简单讲述了SMO的一些基本概念,实际上SMO体系结构远不止周公在上一篇中讲述的那么简单,下图是MSDN上给出的一个完整的 ...
- HDU 1877 另一个版本 A+B
另一个版本 A+B Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...