Laravel中通过查询语句筛选访问日期时年龄<24岁的记录
问题描述
我有一个visits表,结构及数据如下:
visits dob[varchar(50)] visitdate[Date] name[varchar(16)] 09/16/2001 2022-11-01 A 09/26/1966 2022-11-01 B 09/21/1999 2022-11-02 C 09/24/2000 2022-11-02 D
我需要获取访问日期时年龄小于24岁的记录,目前是通过循环过滤实现的:
function get_age_group($dob, $visitDate) { $dob = explode("/", $dob); $dob = new DateTime($dob[2] . '-' . $dob[0] . '-' . $dob[1]); $visitDate = new DateTime($visitDate); $diff = $visitDate->diff($dob); return $diff->y; } // 查询代码 $visits = DB::table('visits')->get(); foreach ($visits as $row) { $age = get_age_group($row->dob, $row->visitdate); if(($age < 24)) { // 处理符合条件的数据 } }
希望直接在Laravel查询语句中添加where子句替代循环,实现类似$visits = DB::table('visits')->where(?)->get();的写法。
解决方案
由于dob字段是mm/dd/yyyy格式的字符串,需要先在SQL层面转换为日期格式,再计算访问日期时的年龄是否小于24岁。以下是针对MySQL的两种实现方式:
方式一:直接计算年龄差值
利用MySQL的STR_TO_DATE转换日期格式,再用TIMESTAMPDIFF精确计算年龄:
$visits = DB::table('visits') ->whereRaw("TIMESTAMPDIFF(YEAR, STR_TO_DATE(dob, '%m/%d/%Y'), visitdate) < 24") ->get();
说明:
STR_TO_DATE(dob, '%m/%d/%Y'):将mm/dd/yyyy格式的字符串转换为数据库可识别的日期类型TIMESTAMPDIFF(YEAR, 出生日期, 访问日期):精准计算两个日期的年份差,即用户访问时的实际年龄- 通过判断年龄小于24,直接过滤出符合条件的记录
方式二:反向推导出生日期范围
换一种思路:计算访问日期往前推24年的日期,只要出生日期晚于该日期,就说明用户访问时年龄小于24岁:
$visits = DB::table('visits') ->whereRaw("STR_TO_DATE(dob, '%m/%d/%Y') > DATE_SUB(visitdate, INTERVAL 24 YEAR)") ->get();
说明:
DATE_SUB(visitdate, INTERVAL 24 YEAR):得到访问日期24年前的日期- 出生日期晚于该日期,意味着用户在访问时还未年满24岁,逻辑和方式一等价
其他数据库适配(以PostgreSQL为例)
如果使用PostgreSQL,函数会有差异,可参考以下写法:
$visits = DB::table('visits') ->whereRaw("EXTRACT(YEAR FROM AGE(visitdate, TO_DATE(dob, 'MM/DD/YYYY'))) < 24") ->get();
优化建议
建议后续将dob字段修改为DATE类型,避免每次查询都要做格式转换,提升查询性能。
内容的提问来源于stack exchange,提问作者Lokendra Singh Panwar
相关产品推荐
相关产品推荐

