zoukankan      html  css  js  c++  java
  • 关于SQL的几道小题详解

    关于SQL的几道小题详解

          当我们拿到题目的时候,并不是急于作答,那样会得不偿失的,而是分析思路,采用什么方法,达到什么目的,还要思考有没有简单的方法或者通用的方法等等,这样才会达到以一当十的效果,这样的惯性思维其实早在我们度高中的时候就被领教了,所谓“万变不离其宗”吧。以下各题来自日常所见,或QQ群,或面试题,或博客园。

         题目一:如下表所示,现需要按照收款员统计收款和退款合计金额。

         实现结果需如下显示:

          分析:想要的结果(记为表B)和源数据(记为表A)相比,有共同的列(收款员),不同的是表A的金额根据标记和收款员分成了两列,所以这个需求可以用语言表述一下:首先根据收款员分组(group by),然后当标记为“收”时,金额计入收款合计(sum);当标记为“退”时,金额计入退款合计(sum)。当……时……,这不就是SQL的条件判断嘛?盘点SQL的条件语句不多,if……else……case……when……then……else……end。这样问题就迎刃而解了。

         解决方案如下:

     1 with ta as
     2 (select '' as 标记,'100' as 收款员,150 as 金额
     3  union
     4  select '','100',375
     5  union
     6  select '退','100',78
     7  union select '','200',74
     8 )
     9 
    10 select 收款员,sum(case when 标记='' then 金额 else 0 end) as 收款合计,
    11        sum(case when 标记='退' then 金额 else 0 end) as 退款合计 from ta
    12        group by 收款员

          题目二:如下表A(左边)职员信息表,其中ID为职员工号,name为职员姓名;表B(右边)为职员任务分配表,其中ID为职员工号(和表A中ID对应),Task为任务编号。

                                                                                                                                          

         现需求每个职员的任务数。结果如下显示:

           其实原题是这样的:只有一张表B,求求每个职员的任务数。没有找到比较好的方法实现,不做讨论,欢迎高人指点。

          分析:此题的难点在于表B中的ID复杂表示,其实这样有悖于数据库的设计原则,理应表A和表B的ID一一对应。既然是题,我们只能从当前的条件入手了,攻破难点的关键在于判断A中ID在B中ID出现与否,如果出现那么如何统计出现的次数。判断出现与否需要用到函数CHARINDEX

         解决方案如下:

     1 --创建测试数据
     2 WITH TA
     3 AS
     4 (SELECT '1,2' AS ID,'job1' AS task
     5 UNION SELECT '1,2,3','job3'
     6 UNION SELECT '2,3','job2'
     7 UNION SELECT '3,4,5','job4')
     8 ,TB AS  
     9 (SELECT '1' AS ID,'张三' as name
    10 UNION SELECT '2','王二'
    11 UNION SELECT '3','李四'
    12 UNION SELECT '4','李明'
    13 UNION SELECT '5','王五')
    14 
    15 SELECT B.ID,B.name,COUNT(1) AS TASKS
    16  FROM TA A,TB B
    17   WHERE CHARINDEX(B.ID,A.ID)>0
    18   GROUP BY B.ID,B.name
    19   order by B.ID 

        题目三:原题参见博客:http://www.cnblogs.com/Lumia1020/p/4571301.html

          如下表City所示,code为行政区域码(六位数字,前两代表省级,中间两位代表市级,最后两位代表县级,不考虑xx00xx情况),city为城市名称,CCode为该城市所属的省级或者市级行政区域码。

           现需求如下结果:

           

         分析:分析表city,code的含义十分明显,所需要的结果也很明显,如果是省就是显示省份;是市则显示为所属省级+市级;是县级则显示为所属省级+所属市级+县级。貌似可以用题目一分析中提到的SQL条件语句实现,但是转念一想,还是有差别,这里需要先判断city属于省级?市级?县级?然后在对应起来的,这样还得有参照表,复杂了。回到结果表中来进行分析,其实判定city属于省市县的问题并不难,code的含义已经说明了,只要转换表述:在表City中,当code的后四位为“0000”时,肯定是省级;当code的后两位为“00”,并且后四位不为“0000”时,肯定是市级;当code后两位不为“00”时,为县级。这样省市县的判定就一目了然了,然后,根据市级编码追朔所属的省级,并得出所属省级+市级,县级追朔所属的市级,得出所属省级+所属市级+所属县级,通过运用这种简单的递归思想,解决方案便跃然纸上了。

         解决方案如下:

     1 --测试数据
     2 with ta as
     3 (select '110000' as code, '北京市' city, '110000' Ccode
     4 union
     5 select N'110200', N'西城区', N'110200'
     6 union
     7 select N'110300', N'崇文区', N'110300'
     8 union
     9 select N'430000', N'湖南省', N'430000'
    10 union
    11 select N'430100', N'长沙市', N'430100'
    12 union
    13 select N'430101', N'望城县', N'430100')
    14 
    15 select * into City from ta
    16 
    17 select * from City;
    18 
    19 --解决方案
    20 with ta
    21 as(
    22 --省级
    23 select code,city,Ccode,city content from City where right(code,4)='0000'),
    24 tb as(
    25 --市级
    26 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)
    27 and right(b.code,2)='00' and right(b.code,4)<>'0000'),
    28 tc as(
    29 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)
    30 and right(c.code,2)<>'00')
    31 select * from ta
    32 union
    33 select * from tb
    34 union
    35 select * from tc

           通过上述几道小题,常思常新,温故了SQL的部分知识,当然方法很多,变式很多,如题目二统计表B中每个Task的人数等。不足之处,欢迎各位指点!

  • 相关阅读:
    UI第十七讲.图片异步加载(包括第三方), KVO, KVC
    第二十一讲.UICollectionView(集合视图)以及瀑布流效果, 通知中心(NSNotificationCenter).
    UI第十九讲:数据库
    UI第十八讲.初级数据持久化 (沙盒, 简单写入对象, 归解档, NSUserDefaults写入读取文件 )
    第十四讲(下) 可视化方式的实现通讯录.(及storyboard方式)
    第十六讲.网络编程 (HTTP协议)
    wslgit
    MyBatis时间比较
    layer开启与关闭加载层
    MyBatis中choose when正确写法
  • 原文地址:https://www.cnblogs.com/zhangbc/p/4576101.html
Copyright © 2011-2022 走看看