SQL 查询本月无数据用上个月的数据

前言

因为标题有长度限制,先简要说明一下应用场景。比如我们要查一段时间范围内(2013-08-01至2013-12-31)每个月每个运营商的用户总量,每个运营商用户量每个月更新的时间可能不同也可能该月没有数据,如果某个运营商本月用户量没有值,则用上个月的用户量。

下面就给大家一步一步分析,解决该问题。

1.  创建基础的表和示例数据

首先我们需要创建一个用户量表,具体的表结构和表内容如下:

2.  分析题目要求

通过对前言中描述的应用场景分析,我们可以得出以下几点讯息:

l  获取一个时间范围内的各个运营商的各个月的数据

l  个别运营商本月无数据的用距离本月日期最近的数据

结合上边的示例数据分析,也就是如果我们要求2013-09-01到2013-12-31之间各个运营商这几个月的数据得到的结果应该是如下图所示:

上图中红框标注的部分在数据库中是不存在的,也就是说12月份数据库中没有数据,我们就使用距离12月最近的数据。

3.  逐步解决问题

题目要求的是求一个时间段内的几个月的各运营商的用户总量,这样我们先把问题分解,先求出一个月的各运营商的用户总量。

3.1要求一个月的各运营商的用户总量,我们先求出该月或者据该月最近的用户总量更新的日期。

为了更好的做演示示例,12月份没有数据,我们就用12月份来做演示。

具体代码如下:

select SP_Name as name,MAX(Create_Date) as "group" from UserCount
where Create_Date<'2013-12-31'
group by SP_Name

  

执行结果如下:

3.2求出该月的最近的更新日期后,求出相对应的值.

具体代码如下:

with sub as
(
select SP_Name as name,MAX(Create_Date) as "group" from UserCount
where Create_Date<'2013-12-31'
group by SP_Name
)
select us.SP_Name as "name",'201312' as "date" ,SUM(us.User_Count) as "value"
from UserCount us
right join sub s on s.name=us.SP_Name
where us.Create_Date=s."group"
group by us.SP_Name,s."group"

  

执行结果如下:

这样我们就完成的题目所需的求出某个月的用户量,且该月没有值,采用距离该月日期最近的更新日期的值。

3.3 循环求出每个月的用户量,最后将几个月的用户量合并

但是,问题又来了,既然我们求出了某一个月的值,那么如何求出一个时间范围内也就是几个月的用户量呢?

很明显,这需要通过循环分别查出时间范围内每一个月的值,然后将这些值Union就可以了。为了考虑到实用性,我们将这一部分的操作封装在一个函数里。

具体代码如下:

create procedure getMonthData(@str1 varchar(200),@str2 varchar(200))--传入两个日期范围的字符串,形如:20130901,
as
declare @date1 date;--定义两个日期变量,用来将传入的字符串转换为时间,并作为循环的控制条件
declare @date2 date;
begin
set @date1=DATEADD("mm",1,cast(@str1+'01' as date));--处理传入的字符串,转换为时间默认为,
set @date2=DATEADD("mm",1,cast(@str2+'01' as date));
create table #temp1 (name varchar(200),"group" varchar(200),"value" int);--创建一个临时表用来存储每次循环产生的数据,相当于将每个月查询出的数据union
while @date1<=@date2
begin
with sub as --求出当前月,用户量最新的更新日期
(
select SP_NAME as "name",MAX(Create_Date) as "value"
from UserCount
where Create_Date<@date1
group by SP_NAME
),
sub1 as --求出当前月各运营商的用户总量
(
select SP_NAME as "name",@str1 as "group",MAX(User_Count) as "value"
from UserCount ue
right join sub s on s."name"=ue.SP_NAME
group by ue.SP_NAME
)
insert into #temp1 select * from sub1 --将当前月的用户总量插入的临时表保存
set @date1=dateadd("mm",1,@date1)--更改循环条件
set @str1=cast(CAST(@str1 as int )+1 as varchar(200))--更改月份
end
select * from #temp1;--查询临时表,展现所有的数据
end

  

具体结果如下:

这样就基本上上完成的题目的要求了,但是,这还不是最完美的,请注意上边黄色高亮部分,如果日期为参数为201309,201401时,查询出来的结果就是这样的。

也就是说在日前跨年的情况下,月份的展示是乱的,这样我们可以再创建一个函数处理这样的问题。

具体代码如下:

create  function modifydate(@date varchar(200))
returns varchar(200)
as
begin
declare @month int;
set @month=cast(SUBSTRING(@date,5,2) as int)
if @month>12
begin
set @date=cast(cast(SUBSTRING(@date,1,4) as int)+@month/12 as varchar) + (case when @month%12=0 then '01' when @month%12<10 then '0'+CAST(@month%12 as varchar) else CAST(@month%12 as varchar) end)
end
return @date;
end

  

这样就很好的解决了跨年时显示的日期格式不正确的问题,同时还需要将上边高亮的那一行代码改为如下代码即可:

set @str1=dbo.modifydate(cast(CAST(@str1 as int )+1 as varchar(200)))--更改月份

 

好了,今天就总结到这里了,希望能给大家一些帮助。主要是一个思路吧,之前写过一个同样需求的sql,当时就只是用一个sql语句就实现了,但是时间长了,忘了怎么做的,回头找找,再跟大家分享。

SQL 查询本月无数据用上个月的数据问题的更多相关文章

  1. 用sql查询当天,一周,一个月的数据

    用sql查询当天,一周,一个月的数据   数据查询,不管在网站还是在系统,都很常见,下文是介绍最常见的以日期查询的语句 select * from ShopOrder where datediff(w ...

  2. hibernate在使用sql查询query自动转化成model类型数据,query.addEntity

    hibernate使用自动的hql查询或者其封装的查询方法都能字段转化成对象 而如果在hibernate中使用sql时大多返回为Object[]对象 那么如何将object[]转换成model呢,答案 ...

  3. sql 查询表格中多列重复的数据并显示该表的其他列

    我们一般情况下通过分组函数group by来查询重复的列 ) R 但是查询出的结果不能显示该表的其他列 想要查询一张表中有多个列重复的数据且也要显示该表的其他列 SELECT M.* FROM [db ...

  4. sql 查询最近30分钟或者自定义时间数据

    ) FROM dual; 30分钟或者自定义

  5. sql 查询一段时间内某个时间点数据

     SELECT  CONVERT(VARCHAR(10), dtCreateTime, 120) AS dtStatisticsCreateDate, COUNT(1) AS nStatisticsC ...

  6. SQL查询(笔记2——实体查询)

    SQL查询(笔记2——实体查询) 二.实体查询 如果查询返回了某个数据表的全部数据列,且该数据表有对应的持久化类映射,我们就把查询结果转换成实体查询.将查询结果转换成实体,可以使用SQLQuery提供 ...

  7. SQL查询语句 [2]

    一.快捷查询 快捷查询方式是一种多字段查询的简化写法,在多个字段之间用'|'隔开表示OR,用'&'隔开表示 AND. 1.不同字段相同查询条件 在  Home/controller/UserC ...

  8. 数据库查询性能 LinqDB vs Sql查询

    使用LinqDB查询Sqlite数据库数据,不管是大数据还是少量的数据,感觉特别耗时,尤其是首次查询 一个含有2.7万条数据的数据表 首次查询: 查询2.7万条数据,耗时1s 查询指定的1条数据,也要 ...

  9. MySQL查询今天/昨天/本周、上周、本月、上个月份数据的sql代码

    MySQL查询本周.上周.本月.上个月份数据的sql代码 作者: 字体:[增加 减小] 类型:转载 时间:2012-11-29我要评论 MySQL查询的方式很多,下面为您介绍的MySQL查询实现的是查 ...

随机推荐

  1. 通知(Notification) 、 应用间通信(一)

    1 使用通知中心发送消息 1.1 问题 当一个对象需要向多个接受者发送消息的,或者不用知道消息的接收者是谁,就可以使用IOS提供的NSNotificationCenter通知中心,本案例使NSNoti ...

  2. linux性能监控基础命令

    压力测试监控下系统性能方法之一 #top 该命令监控的是进程的信息 看图逐行意义 top:执行命令的之间 up:已经执行了277天 2users:目前有两个使用者,使用#who可以查看具体的使用者详情 ...

  3. ci(转)

    1  从代码管理器签出源文件 2  修改代码 3  编译代码 4  遇到错误,转到2继续修改直到达到预期 5  运行单元测试,期望所有的测试绿色(通过) 6  单元测试出错,转入2 7  重构代码,按 ...

  4. OpenFlow Switch学习笔记(三)——Flow Tables

    这次我们主要讨论下OpenFlow Switch的核心组件之一——Flow Tables,以了解其内部的 matching 以及 action handling 机制.下文将会分为几个部分来逐步详述O ...

  5. java parseint()

    static int parseInt(String s) static int parseInt(String s, int radix) parseInt(String s)表示将 “数字” 转换 ...

  6. leetcode 123. Best Time to Buy and Sell Stock III ----- java

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  7. ISBN号码

    总时间限制:  1000ms 内存限制:  65536kB 描述 每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字.1位识别码和3位分隔符,其规定格式如"x-xxx- ...

  8. 求10000以内n的阶乘

    总时间限制:  5000ms 内存限制:  655360kB 描述 求10000以内n的阶乘. 输入 只有一行输入,整数n(0<=n<=10000). 输出 一行,即n!的值. 样例输入 ...

  9. spark新能优化之shuffle新能调优

    shuffle调优参数 new SparkConf().set("spark.shuffle.consolidateFiles", "true") spark. ...

  10. Linux查找文件

    which 可以查找可执行文件的位置 evilxr@IdeaPad:~$ which ping /bin/ping whereis whereis -m 可查询到命令的帮助文档在什么地方 evilxr ...