上一篇:array_merge函数的详细用法(2019-12-05 23:20:19)
文章大纲

php月周时间范围筛选查询的注意事项

2019-12-07 20:51:10

现有一个业务数据表栏目大概如下所示:

id          int 记录id
group_id    int 分组id
income      int 收入
expense     int 开支
month_date  date  月份时间,例如:2019-12-01
week        int 第几周


我要实现的是获取某小组在任意时间范围之间的收入、开支及利润统计。


由于数据是按某月第几周的方式来新增的,而筛选的时间选择是年-月-日的方式,所以筛选时间的条件必须先由年-月-日格式转为某月几周的形式。这个转换过程本文就不讲述了。


我们就直接看,两个某月某周格式的时间范围,统计是如何实现的。


用的是laravel框架,本人一开始写的代码如下:

$startMonth = '2019-11-01';
$startWeek	= 2;
$endMonth   = '2019-12-01';
$endWeek	= 2;
$query = Finance::where(function($outQuery) use($startMonth, $startWeek, $endMonth, $endWeek){
	$outQuery->orWhere(function($query) use($startMonth, $startWeek){
		$query->where('month_date', $startMonth)
			  ->where('week', '>=', $startWeek);
	})
	->orWhere(function($query) use($startMonth, $endMonth){
		$query->where('month_date', '>', $startMonth)
			  ->where('month_date', '<', $endMonth);
	})
	->orWhere(function($query) use($$endMonth, $endWeek){
		$query->where('month_date', $endMonth)
			  ->where('week', '<=', $endWeek);
	});
});	


上面代码逻辑有漏洞,你能看出来吗?


将上面代码转换成sql语句,如下:

select * from zhai14_cost 
where group_id = ? 
and (
	(date_time = ? and week >= ?) 
	or (date_time > ? and date_time < ?) 
	or (date_time=? and week <=?)
)


你还能看出来问题吗?


特殊情形是,当开始时间和结束都是同一个月同一周的时候,应该实现的功能就是查询那一个月那一周的数据。但是上面代码并不能达到这一目的。


为了方便分析,我们假定时间都是11月的第3周。

将数值代入到上面sql语句中去,得到如下:

(date_time = '2019-11-01' and week >= 3) 
or (date_time > '2019-11-01' and date_time < '2019-11-01') 
or (date_time='2019-11-01' and week <=3)


中间一行是空区间,就可以忽略了。

剩下第一行和第三行所形成的范围就成了2019-11-01这整个月的时间了,而实际应该就只是2019年11月的第3周这一周的时间而已。


这就是上面代码的漏洞所在。


修补方法就是将开始时间和结束时间相等的情形考虑进去,最终代码如下所示:

if( $startMonth == $endMonth ){
	if( $startWeek == $endWeek ){
		$query = Finance::where('month_date', $startMonth)
					->where('week', $startWeek);
	}else{
		$query = Finance::where('month_date', $startMonth)
					->where('week', '>=', $startWeek)
					->where('week', '<=', $endWeek);
	}
}else{

	$query = Finance::where(function($outQuery) use($startMonth, $startWeek, $endMonth, $endWeek){
		$outQuery->orWhere(function($query) use($startMonth, $startWeek){
			$query->where('month_date', $startMonth)
				  ->where('week', '>=', $startWeek);
		})
		->orWhere(function($query) use($startMonth, $endMonth){
			$query->where('month_date', '>', $startMonth)
				  ->where('month_date', '<', $endMonth);
		})
		->orWhere(function($query) use($$endMonth, $endWeek){
			$query->where('month_date', $endMonth)
				  ->where('week', '<=', $endWeek);
		});
	});
}


本文是翟码农个人博客蓝翟红尘里php分类下的文章,转载请注明出处:http://www.zhai14.com/blog/fcece0fe04e1951cc7731de3a13ddb07.html




上一篇:array_merge函数的详细用法(2019-12-05 23:20:19)
我要评论
评论列表