【sql查询】使用sql查询一个物品是否在有效期内的方法(数据库无这个字段 通过生产日期和保质期进行计算得出)

事件起因

今天在写一个查询一个产品的使用期限的时候遇到这个问题,物品的使用期限问题 稍微延伸一下的话 就有很多方面的应用 比如说 食品的生产日期和保质期,危险物品的定期检测等系列问题 所以特此来写篇文章来记录一下 以便自己以后遇到相似的问题 或者 后来者遇到相似的问题

查看上面的目录 不需要听我在这儿逼逼叨叨的 ,可以直接跳转到实际应用场景去查看对应的sql语句的写法 书写事件经过 只是给自己未来看的 顺便描述下 在什么样的场景下可能会用到这样的写法

问题描述:

当前的需求是 一张mysql数据库表里面 有一个产品的众多信息 有两列分别是产品的生产日期和有效期 现在要求能够通过前端控制查询超限的物品,并将他们按不同的颜色显示出来

sql给后端提供数据

因为这个问题是在对公司的项目进行业务增加的时候注意到的,所以不方便展示那个项目的数据库,但是我们可以来还原一下大致的业务场景,所以咱们先来建一个数据库表:
在这里插入图片描述
主要关注start_time,keep_time 分别可以表示为生成日期和有效期

然后向这个表插入两个数据:
在这里插入图片描述
根据使用start_time和keep_time (笔者的当前时间(执行这个sql的时间)是2022.02.09) 来看 第一条数据是过期了 第二条数据没有过期, 然后写下了让每一个物品的数据都通过聚合函数的方式来生成一条过期状态的表示(好让后端返回的每个物品的数据信息中带一个是否过期的字段 方便前端对过期的数据以不同的方式(颜色或其他方式)进行展现) 的sql:

SELECT *,DATE_ADD(start_time,INTERVAL keep_time month) < NOW() as overTimeStatus FROM `goods`

该条sql语句的执行效果是将原来的所有数据列后直接增加一列为 overTimeStatus 用于表示是否超限
sql的执行结果如下:
在这里插入图片描述
如图 最后一列的overTimeStatus 就是用于表示是否超限(超出使用期限–过期) 1表示已经超限,0表示未超限(在使用期限内)

实际应用场景

在具体的业务中,我们要查询的数据列可能有很多列,就比如下面这个:
在这里插入图片描述
复制出来有这么多:

SELECT
        d.`name` AS dept_name,
        h.house_name AS houseName,
        h2.house_name as newspare24Name,
        d1.name as bankDeptName,
        d2.name as useDeptName,
        d3.name as oldDeptName,
        cs.`course_name` AS course_name,
        a.create_time,
        a.tb_config_id,
        a.update_time,
        c.tb_type,
        a.remark,
        a.overTimeStatus,
        DATE_FORMAT(a.spare2,'%Y-%m-%d') AS spare2
        
        FROM (select *,DATE_ADD(spare2,INTERVAL spare14 month) <![CDATA[<]]> now() as overTimeStatus from tb_assets)  AS a
        LEFT JOIN sys_dept AS d ON a.dept_id = d.dept_id
        LEFT JOIN sys_dept AS d1 ON a.spare9 = d1.dept_id
        LEFT JOIN sys_dept AS d2 ON a.spare10 = d2.dept_id
        LEFT JOIN sys_dept as d3 on a.spare23 = d3.dept_id
        LEFT JOIN sys_house AS h ON a.spare24 = h.house_id
        LEFT JOIN sys_house AS h2 ON a.newspare24 = h2.house_id
        LEFT JOIN tb_config AS c ON a.tb_config_id=c.tb_config_id
        LEFT JOIN sys_course as cs on a.course_id = cs.course_id
        where a.overTimeStatus = 1
        ORDER BY
        a.create_time DESC,
        a.assets_id DESC

当然 我将where那些赛选条件都给去除了,实际要更长一点,
注意上面的增加一列的方式是放在 from 中的
聚合函数计算得出的overTimeStatus 的值 1表示: 已经过期了 0表示: 还在有效期限内
sql语句的执行顺序如下图所示:
sql的执行顺序
所以对于最外层的查询语句的select来说,优先要执行 from 里面的内容 而from里面又是一个子查询 它会生成一个新的集合, 所以优先执行了子查询里面的内容 子查询里面的内容就是将通过聚合函数的方式来给原本的数据表增加一列新的值,也就是超限状态

优点:在进行其他所有的数据筛选条件前就直接将所有的列的是否超限状态给计算出来,能够把这列的超限状态作为后面的筛选条件比如说where overTimeStatus = 1 要知道overTimeStatus 这一列在数据本身是不存在的 而是通过聚合函数计算出来的值
缺点:有优点就必定会存在它的缺点,当面临一个表中存在大量的数据时,比较花费时间 因为不管那一列是否是满足自己其他的筛选条件 都将优先计算完所有的行生成一个临时表,然后对这个临时表进行操作 这样在进行一切操作前 就处理所有的数据列去执行一遍聚合函数的方式有一些慢

针对上述sql缺点进行的一点改进

首先要清楚:聚合函数的结果 要作为一列的返回值 故将它添加到select语句中去

select (这儿一堆我就不写了),DATE_ADD(spare2,INTERVAL spare14 month) <![CDATA[<]]> now() as overTimeStatus from tb_assets
where (其他筛选条件) AND DATE_ADD(spare2,INTERVAL spare14 month) <![CDATA[<]]> now()= 1 

该方式将用于计算是否过期的状态的字段分别在select和where中进行计算了两次,根据sql执行顺序 where中先执行,但是执行后的结果不能够保存 所以要得到结果值时再要将筛选条件后的结果执行一遍聚合函数得到这个列 其他筛选条件 放在了这个是否过期的状态的判断字段前面 先通过其他的条件对范围进行了进一步缩小后 再来对这个结果范围进行计算 计算的次数将会大幅度减少 当面临大量的数据时,这不失为一种办法

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿,葱来了-C is coming

老板大气

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值