关于SQL的几道小题详解(sql进阶)
当我们拿到题目的时候,并不是急于作答,那样会得不偿失的,而是分析思路,采用什么方法,达到什么目的,还要思考有没有简单的方法或者通用的方法等等,这样才会达到以一当十的效果,这样的惯性思维其实早在我们度高中的时候就被领教了,所谓“万变不离其宗”吧。以下各题来自日常所见,或QQ群,或面试题,或博客园。
题目一:如下表所示,现需要按照收款员统计收款和退款合计金额。
实现结果需如下显示:
分析:想要的结果(记为表B)和源数据(记为表A)相比,有共同的列(收款员),不同的是表A的金额根据标记和收款员分成了两列,所以这个需求可以用语言表述一下:首先根据收款员分组(group by),然后当标记为“收”时,金额计入收款合计(sum);当标记为“退”时,金额计入退款合计(sum)。当……时……,这不就是SQL的条件判断嘛?盘点SQL的条件语句不多,if……else……和case……when……then……else……end。这样问题就迎刃而解了。
解决方案如下:
with ta as (select '收' as 标记,'100' as 收款员,150 as 金额 union select '收','100',375 union select '退','100',78 union select '收','200',74 ) select 收款员,sum(case when 标记='收' then 金额 else 0 end) as 收款合计, sum(case when 标记='退' then 金额 else 0 end) as 退款合计 from ta group by 收款员
题目二:如下表A(左边)职员信息表,其中ID为职员工号,name为职员姓名;表B(右边)为职员任务分配表,其中ID为职员工号(和表A中ID对应),Task为任务编号。
现需求每个职员的任务数。结果如下显示:
其实原题是这样的:只有一张表B,求求每个职员的任务数。没有找到比较好的方法实现,不做讨论,欢迎高人指点。
分析:此题的难点在于表B中的ID复杂表示,其实这样有悖于数据库的设计原则,理应表A和表B的ID一一对应。既然是题,我们只能从当前的条件入手了,攻破难点的关键在于判断A中ID在B中ID出现与否,如果出现那么如何统计出现的次数。判断出现与否需要用到函数CHARINDEX。
解决方案如下:
--创建测试数据 WITH TA AS (SELECT '1,2' AS ID,'job1' AS task UNION SELECT '1,2,3','job3' UNION SELECT '2,3','job2' UNION SELECT '3,4,5','job4') ,TB AS (SELECT '1' AS ID,'张三' as name UNION SELECT '2','王二' UNION SELECT '3','李四' UNION SELECT '4','李明' UNION SELECT '5','王五') SELECT B.ID,B.name,COUNT(1) AS TASKS FROM TA A,TB B WHERE CHARINDEX(B.ID,A.ID)>0 GROUP BY B.ID,B.name order by B.ID
题目三:原题参见这篇文章:https://www.jb51.net/article/67885.htm
如下表City所示,code为行政区域码(六位数字,前两代表省级,中间两位代表市级,最后两位代表县级,不考虑xx00xx情况),city为城市名称,CCode为该城市所属的省级或者市级行政区域码。
现需求如下结果:
分析:分析表city,code的含义十分明显,所需要的结果也很明显,如果是省就是显示省份;是市则显示为所属省级+市级;是县级则显示为所属省级+所属市级+县级。貌似可以用题目一分析中提到的SQL条件语句实现,但是转念一想,还是有差别,这里需要先判断city属于省级?市级?县级?然后在对应起来的,这样还得有参照表,复杂了。回到结果表中来进行分析,其实判定city属于省市县的问题并不难,code的含义已经说明了,只要转换表述:在表City中,当code的后四位为“0000”时,肯定是省级;当code的后两位为“00”,并且后四位不为“0000”时,肯定是市级;当code后两位不为“00”时,为县级。这样省市县的判定就一目了然了,然后,根据市级编码追朔所属的省级,并得出所属省级+市级,县级追朔所属的市级,得出所属省级+所属市级+所属县级,通过运用这种简单的递归思想,解决方案便跃然纸上了。
解决方案如下:
--测试数据 with ta as (select '110000' as code, '北京市' city, '110000' Ccode union select N'110200', N'西城区', N'110200' union select N'110300', N'崇文区', N'110300' union select N'430000', N'湖南省', N'430000' union select N'430100', N'长沙市', N'430100' union select N'430101', N'望城县', N'430100') select * into City from ta select * from City; --解决方案 with ta as( --省级 select code,city,Ccode,city content from City where right(code,4)='0000'), tb as( --市级 select b.code,b.city,b.Ccode,a.city+','+b.city as content from ta a,City b where left(a.Ccode,2)=left(b.Ccode,2) and right(b.code,2)='00' and right(b.code,4)<>'0000'), tc as( select c.code,c.city,c.Ccode,b.content+','+c.city content from tb b,City c where left(b.Ccode,4)=left(c.Ccode,4) and right(c.code,2)<>'00') select * from ta union select * from tb union select * from tc
通过上述几道小题,常思常新,温故了SQL的部分知识,当然方法很多,变式很多,如题目二统计表B中每个Task的人数等。不足之处,欢迎各位指点!
相关文章
ROW_NUMBER SQL Server 2005的LIMIT功能实现(ROW_NUMBER()排序函数)
SQL Server 2005新增了一个ROW_NUMBER()函数,通过它可实现类似MySQL下的LIMIT功能。下面的语法说明摘自SQL Server 2005的帮助文件2012-06-06Mybatis非配置原因,导致SqlSession was not registered for synchroniza
本文主要介绍Mybatis非配置原因出错,这里对这个出现的问题做了详细介绍,及解决办法,有兴趣的小伙伴可以参考下2016-09-09SQL Server 日期函数CAST 和 CONVERT 以及在业务中的使用介绍
。最近时间刚从客户端转入后台写服务,对于后台数据库以及服务的书写完全是个小白,所以最近写的肯定没有太多技术含量2013-01-01SQL Server2019数据库备份与还原脚本(批量备份)
本文主要介绍了SQL Server2019数据库备份与还原脚本,数据库可批量备份,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2021-11-11
最新评论