[aaronyang原创] Mssql 一张表3列的sql面试题,看你sql学的怎么样

Student表的样子:

题目1:

考点:逻辑思维 筛选出学生中所有科目都大于60分的人, 例如:只要有一门低于60分,那么这个人的所有成绩都不要显示了,这里B的数学成绩只有13分,所以B的所有科目都不显示

显示的样子例如如下:

如果你想自己尝试,你可以先不看下面的内容

我的思路:

一开始想到group,having,那就顺便复习下group和having的用法 我这样子写的,但是还是没有达到题目的要求

SELECT [StuName],MAX(StuSubject) AS ‘StuSubject‘,MAX(StuGrade) AS ‘StuGrade‘
 FROM [dbo].[Student]
 GROUP BY StuName,StuGrade Having MIN(StuGrade) >= 60

效果:

失败的原因是

所有科目,只要有一门低于60分,那么这个人都不要显示了,这里B的数学成绩只有13分,所以B的所有科目都不显示 这样子写跟  select * FROM Student WHERE StuGrade >= 60 有什么区别呢? 所以想复杂了,换个思路,先找出所有低于60分的,由于可能一个人有多门成绩低于60分,那么stuname就会出现多次,所以还需要distinct,最终实现效果的sql如下:

 SELECT * FROM Student WHERE StuName not in(SELECT DISTINCT(StuName) FROM Student WHERE StuGrade < 60)

好了,说了这么多,因为长时间使用orm的后遗症,所以sql可能会忘记,本题目①考验思路,②复习group和having

拓展:例如不按照要求这样写sql

SELECT [StuName],StuGrade
 FROM [dbo].[Student]
 group by StuName having stugrade < 60

这样有个错误: HAVING 子句中的列 ‘dbo.Student.StuGrade‘ 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中 所以having的用法,having是对group组中的数据再次进行筛选,但是筛选的组要在group by后面出现 关于group by

SELECT [StuName],StuGrade
 FROM [dbo].[Student]
 group by StuName

这样有个错误:选择列表中的列 ‘dbo.Student.StuGrade‘ 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中 所以如果select 后面的列名称在group by中没有出现的时候,就要给该列加个聚合函数 提到聚合函数大家一定会首先想到最常用的:

1、 求个数:count 2、 求总和:sum 3、 求最大值:max 4、 求最小值:min 5、 求平均值:avg 聚合函数中有四个函数是我一直以来几乎就没有用到过的: 1、 求方差:var 2、 求总体方差:varp 3、 标准偏差:stdev 4、 求总体标准偏差:stdevp 除此以外Sql Server中还有几个集合函数: 1、 求校验和:checksum_agg 2、 求个数:count_big 3、 用于测试 cube 或 rollup 空值:grouping

接下来,我们加个WHERE条件,复习 WHERE GROUP Having混用W-G-H

SELECT [StuName],MAX(StuSubject) AS ‘StuSubject‘,MAX(StuGrade) AS ‘StuGrade‘
 FROM [dbo].[Student] WHERE StuGrade>60
 GROUP BY StuName,StuGrade Having MIN(StuGrade) >= 60

======================================本篇文章权限由AaronYang拥有,文章来自www.ayjs.net=======================================

题目2:

考点:sql的横竖转换 增加学生E的成绩

我现在要显示的结果如下:

讲解如下:

① 决定group by列,这里只有StuName不重复,所以group by StuName

SELECT [StuName] FROM [dbo].[Student] GROUP BY StuName

②要被 case when的列,显示出来成绩,所以case 列名 when 成绩,然后技巧的加上其他列

MAX(CASE StuSubject WHEN ‘语文‘ THEN StuGrade ELSE -1 END) AS ‘语文成绩‘

③ 套用一个简单的sql公式,基本成型

SELECT [StuName],
 MAX(CASE StuSubject WHEN ‘语文‘ THEN StuGrade ELSE -1 END) AS ‘语文成绩‘,
 MAX(CASE StuSubject WHEN ‘数学‘ THEN StuGrade ELSE -1 END) AS ‘数学成绩‘,
 MAX(CASE StuSubject WHEN ‘英语‘ THEN StuGrade ELSE -1 END) AS ‘英语成绩‘
 FROM [dbo].[Student] GROUP BY StuName

④把-1变成 缺考 这里有简单的方式,但我还是用绕的方式,顺便复习几种sql的用法

1.  with 临时表的用法

with temp1(StuName,Yuwen,Shuxue,Yinyu) AS (SELECT [StuName],
 MAX(CASE StuSubject WHEN ‘语文‘ THEN StuGrade ELSE -1 END) AS ‘yuwen‘,
 MAX(CASE StuSubject WHEN ‘数学‘ THEN StuGrade ELSE -1 END) AS ‘shuxue‘,
 MAX(CASE StuSubject WHEN ‘英语‘ THEN StuGrade ELSE -1 END) AS ‘yingyu‘
 FROM [dbo].[Student] GROUP BY StuName
 )
 SELECT * FROM temp1
显示的效果跟上面的一样,但是复杂的列变成一列了,此时这张表已经在内存里了,所以不适合几百万条在内存条里了,企业内部开发应该可以。
临时表用完了,会被释放掉,所以在select以后,你再select那种临时表,会报错了,因为不存在了
OK,有了简单的表,接下来复习其他的

2. case when,CAST转换数据类型 我们基于临时表的基础来操作 上面的一种形式  case 列 when 值 then 结果  END ,这个相当于C#的switch用法 第二种形式是表达式 case when 条件 then 结果

with temp1(StuName,Yuwen,Shuxue,Yinyu) AS (SELECT [StuName],
 MAX(CASE StuSubject WHEN ‘语文‘ THEN StuGrade ELSE -1 END) AS ‘yuwen‘,
 MAX(CASE StuSubject WHEN ‘数学‘ THEN StuGrade ELSE -1 END) AS ‘shuxue‘,
 MAX(CASE StuSubject WHEN ‘英语‘ THEN StuGrade ELSE -1 END) AS ‘yingyu‘
 FROM [dbo].[Student] GROUP BY StuName
 )
 SELECT StuName,
 Yuwen=CASE WHEN Yuwen = -1 THEN ‘缺考‘ ELSE CAST(Yuwen AS varchar) END,
 Shuxue=CASE WHEN Shuxue = -1 THEN ‘缺考‘ ELSE CAST(Shuxue AS varchar) END,
 Yinyu=CASE WHEN Yinyu = -1 THEN ‘缺考‘ ELSE CAST(Yinyu AS varchar) END
 FROM temp1
显示结果:
3. 拓展题目,增加一列自动增长列,说白了,也是考验你分页的前提
  3.1 ROW_NUMBER() OVER(order by 要排序的列)
with temp1(StuName,Yuwen,Shuxue,Yinyu) AS (SELECT [StuName],
 MAX(CASE StuSubject WHEN ‘语文‘ THEN StuGrade ELSE -1 END) AS ‘yuwen‘,
 MAX(CASE StuSubject WHEN ‘数学‘ THEN StuGrade ELSE -1 END) AS ‘shuxue‘,
 MAX(CASE StuSubject WHEN ‘英语‘ THEN StuGrade ELSE -1 END) AS ‘yingyu‘
 FROM [dbo].[Student] GROUP BY StuName
 )
 SELECT ROW_NUMBER() OVER(order by StuName) as ID,StuName,
 Yuwen=CASE WHEN Yuwen = -1 THEN ‘缺考‘ ELSE CAST(Yuwen AS varchar) END,
 Shuxue=CASE WHEN Shuxue = -1 THEN ‘缺考‘ ELSE CAST(Shuxue AS varchar) END,
 Yinyu=CASE WHEN Yinyu = -1 THEN ‘缺考‘ ELSE CAST(Yinyu AS varchar) END
 FROM temp1
效果:

  3.2 IDENTITY方法
如果直接使用IDENTITY(int,1,1),会报错误如下:
仅当 SELECT 语句中有 INTO 子句时,才能使用 IDENTITY 函数。
用法:
with temp1(StuName,Yuwen,Shuxue,Yinyu) AS (SELECT [StuName],
 MAX(CASE StuSubject WHEN ‘语文‘ THEN StuGrade ELSE -1 END) AS ‘yuwen‘,
 MAX(CASE StuSubject WHEN ‘数学‘ THEN StuGrade ELSE -1 END) AS ‘shuxue‘,
 MAX(CASE StuSubject WHEN ‘英语‘ THEN StuGrade ELSE -1 END) AS ‘yingyu‘
 FROM [dbo].[Student] GROUP BY StuName
 )
 SELECT IDENTITY(int,1,1) as ID,StuName,
 Yuwen=CASE WHEN Yuwen = -1 THEN ‘缺考‘ ELSE CAST(Yuwen AS varchar) END,
 Shuxue=CASE WHEN Shuxue = -1 THEN ‘缺考‘ ELSE CAST(Shuxue AS varchar) END,
 Yinyu=CASE WHEN Yinyu = -1 THEN ‘缺考‘ ELSE CAST(Yinyu AS varchar) END
 INTO #temp2
 FROM temp1

后面要加个INTO 临时表名,其实此时,MSSQL已经将表存在了系统数据库-tempdb-临时表里面了

所以接下来,你把上面的代码注释掉,都可以SELECT * FROM #temp2了 那么怎样删除临时表,方法1,所有其他本地临时表在当前会话结束时都将被自动删除,不过不断开,再次执行,会报错,因为#temp2表已经存在了。 手动sql删除:

if exists(select * from tempdb..sysobjects where id=object_id(‘tempdb..#temp2‘))
drop table #temp2
go

所以修改后的sql:

if exists(select * from tempdb..sysobjects where id=object_id(‘tempdb..#temp2‘))
drop table #temp2
go

with temp1(StuName,Yuwen,Shuxue,Yinyu) AS (SELECT [StuName],
 MAX(CASE StuSubject WHEN ‘语文‘ THEN StuGrade ELSE -1 END) AS ‘yuwen‘,
 MAX(CASE StuSubject WHEN ‘数学‘ THEN StuGrade ELSE -1 END) AS ‘shuxue‘,
 MAX(CASE StuSubject WHEN ‘英语‘ THEN StuGrade ELSE -1 END) AS ‘yingyu‘
 FROM [dbo].[Student] GROUP BY StuName
 )
 SELECT IDENTITY(int,1,1) as ID,StuName,
 Yuwen=CASE WHEN Yuwen = -1 THEN ‘缺考‘ ELSE CAST(Yuwen AS varchar) END,
 Shuxue=CASE WHEN Shuxue = -1 THEN ‘缺考‘ ELSE CAST(Shuxue AS varchar) END,
 Yinyu=CASE WHEN Yinyu = -1 THEN ‘缺考‘ ELSE CAST(Yinyu AS varchar) END
 INTO #temp2
 FROM temp1

SELECT * FROM #temp2

GO

OK,这道题就啰嗦到这里了

======================================本篇文章权限由AaronYang拥有,文章来自www.ayjs.net=======================================

题目3:

考点: case when 我要显示的结果如下:

提示: 90以上包括90优秀 80-90不包括90良好 60-80 及格 其他不及格   讲解思路: 我们只要基于with temp1的那个sql 在case when里面加几个条件判断就行了

with temp1(StuName,Yuwen,Shuxue,Yinyu) AS (SELECT [StuName],
 MAX(CASE StuSubject WHEN ‘语文‘ THEN StuGrade ELSE -1 END) AS ‘yuwen‘,
 MAX(CASE StuSubject WHEN ‘数学‘ THEN StuGrade ELSE -1 END) AS ‘shuxue‘,
 MAX(CASE StuSubject WHEN ‘英语‘ THEN StuGrade ELSE -1 END) AS ‘yingyu‘
 FROM [dbo].[Student] GROUP BY StuName
 )
 SELECT StuName,
 Yuwen=CASE WHEN Yuwen = -1 THEN ‘缺考‘
 WHEN Yuwen >=90 THEN ‘优秀‘
 WHEN Yuwen <90 AND Yuwen > =80THEN ‘良好‘
 WHEN Yuwen <80 AND Yuwen > =60THEN ‘及格‘
 ELSE ‘不及格‘ END,
Shuxue=CASE WHEN Shuxue = -1 THEN ‘缺考‘
 WHEN Shuxue >=90 THEN ‘优秀‘
 WHEN Shuxue <90 AND Shuxue > =80THEN ‘良好‘
 WHEN Shuxue <80 AND Shuxue > =60THEN ‘及格‘
 ELSE ‘不及格‘ END,
 Yinyu=CASE WHEN Yinyu = -1 THEN ‘缺考‘
 WHEN Yinyu >=90 THEN ‘优秀‘
 WHEN Yinyu <90 AND Yinyu > =80THEN ‘良好‘
 WHEN Yinyu <80 AND Yinyu > =60THEN ‘及格‘
 ELSE ‘不及格‘ END
 FROM temp1
  ======================================本篇文章权限由AaronYang拥有,文章来自www.ayjs.net=======================================

题目4:

考点: 组中筛选top 要求:我要知道每个人在这次考试中他们考的最好的那个科目和分数,并按照姓名排序下 我要显示的结果如下:

答案:

SELECT * FROM Student t WHERE StuGrade=(SELECT MAX(StuGrade) FROM Student where StuName=t.StuName) ORDER BY StuName

恭喜你,已经看到这里了,不错!!Congratulation!

======================================本篇文章权限由AaronYang拥有,文章来自www.ayjs.net=======================================

时间: 2024-10-16 08:27:47

[aaronyang原创] Mssql 一张表3列的sql面试题,看你sql学的怎么样的相关文章

sql 语句 获取某张表某列字段最短的某几行数据

sql 语句 获取某张表某列字段最短的某几行数据 SELECT C_name,C_code FROM Catalog where LEN(C_code)=LEN((SELECT top 1 C_code FROM Catalog order By LEN(C_code))) 原文地址:https://www.cnblogs.com/woniucode/p/10455406.html

1.SQL统计某张表的列数。

select   count(syscolumns.name)    from   syscolumns   ,   sysobjects       where   syscolumns.id   =   sysobjects.id     and   sysobjects.name   =   '表名'

Oracle 将另外一张表的列更新到本表的列

Oracle写法: update temp_agentpay_df q set q.up_batch_bizid=(select c.batch_bizid from temp_df_id c where c.detail_id=q.detail_id) ; Mysql写法: update temp_agentpay_df q,temp_df_id c set q.up_batch_bizid=c.batch_bizid where c.detail_id=q.detail_id; 原文地址:h

关于如何修改一张表中所有行与选定字段的同sql多行语句的添加方法

利用Excel以及word文档进行操作 将表的字段以及数据全部放入Excel表中并保存. 在word表中将写好的sql语句放入文档,利用邮件--选择收件人--使用现有列表--(选择之前做好的Excel表)--插入合并域(添加在sql语句中的条件中)---完成并合并(编辑单个文档选择全部)--完成(不过为了在使用中更加方便,在保存时应当保存为文本文档模式,既是纯文本模式) 原文地址:https://www.cnblogs.com/shuxiaoguang/p/11699432.html

两张表行转列案例

B表 A表 SELECT PV.* FROM ( SELECT b.DeliverLineType, b.DeliverLineTypeName, convert(varchar,CoverageRangeStart)+'-'+convert(varchar,CoverageRangeEnd) AS CoverageRange, b.SpecialRegionFactor, a.Charging, convert(varchar,WeightRangeStart)+'-'+convert(var

转换一个字段中含有多个另外一张表的id | | 行转列

1.Oracle Function --入参:表 id /* cxcyxm02 :操作表,含有一个存储另一张表(xs0101)多个主键id的字段 ids :操作表的主键 id */ CREATE OR REPLACE FUNCTION cxcyxmcyry(ids VARCHAR2) RETURN VARCHAR2 IS tempcyryxx VARCHAR2(1000); cyryxx VARCHAR2(1000); cxcylength number; i number;BEGIN i :=

更新同一张表的整列字段

首先需要先把需要更新的整列结果查询出来. 这里记录下mysql时间的函数:DATE_FORMAT( 字段名, '%Y-%m-%d %H:%i:%s' )  第二个参数是要转换的格式,因为我本来的格式中有毫秒. 以下是举例: 转换的sql :SELECT id AS dd, DATE_FORMAT( created, '%Y-%m-%d %H:%i:%s' ) created2 FROM pe_project_list 整条sql: UPDATE pe_project_listINNER JOIN

一张表保存一个无限级树形目录

一张表保存一个无限级树形目录: /****** Object: Table [dbo].[TreeMenue] Script Date: 08/20/2014 18:03:00 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[TreeMenue]( [ID] [int] IDENTITY(1,1) NOT NULL, [MenueName] [v

无法在同一张表上查询和更新的问题解决方法

一.问题引入 要在一张已存在并且有数据的表上建一个唯一索引,由于建索引的这列有很多重复的数据,导致无法建unique索引!要一条条数据手工删除吗?不!我是工程师,我要用技术的手段删除重复数据.写了一个删除重复数据的sql,如下: delete from entity_tag where id not in (select max(id) from entity_tag group by code ) 写完了,十分兴奋的跑一下这个sql,结果大跌眼镜 [语句1]: delete from enti