yyyy与yyyy-日期比较问题

25 篇文章 0 订阅

1. 问题描述

在2020年1月1日生成的交易日期为2019年12月31日的交易记录文件中,出现了很多历史交易,例如交易时间2019年8月8日的交易数据。在2019年及2020年1月其他时间,未出现该问题。(数据库使用MySQL)

2. 问题分析

查看历史代码,找到生成交易记录文件相关的处理,会从数据库查询前一天的交易记录,生成文件。

从数据库查询前一天的交易记录的SQL语句可以简化如下(字段trans_date为交易日期,类型为字符串):

SELECT * FROM test_table WHERE trans_date >= [前一天日期,格式:yyyy-MM-dd] AND trans_date < [当天日期,格式:yyyy-MM-dd];

在2020年1月1日,生成交易日期为2019年12月31日的交易记录文件时,执行的SQL如下:

SELECT * FROM test_table WHERE trans_date >= '2019-12-31' AND trans_date < '2020-01-01';

执行以上SQL后,查询结果中出现了trans_date为“20190808”等日期的数据。

“20190808”看起来并不满足大于等于’2019-12-31’且小于’2020-01-01’的条件。

执行以下SQL语句,结果为“1 1”,说明“20190808”确实满足大于等于’2019-12-31’且小于’2020-01-01’的条件。

SELECT concat('20190808' >= '2019-12-31' , ' ', '20190808' < '2020-01-01');

查看’-'与’0’对应的ASCII码的十六进制:

SELECT concat(hex('-'), ' ', hex('0'));

以上结果为“2D 30”,即’-'的ASCII码为0x2D,‘0’的ASCII码为0x30,’-'小于0~9的任意数字。

以上的日期比较SQL语句可以简化如下:

SELECT concat('20190' >= '2019-', ' ', '201' < '202');

由于’0’大于’-’,且’1’小于’2’,因此以上两个条件均能满足,上述执行结果为“1 1”。

在2019年的其他日期,例如2019年12月31日执行以上SQL时,SQL语句如下:

SELECT concat('20190808' >= '2019-12-30' , ' ', '20190808' < '2019-12-31');

后一个条件不满足,执行结果为“1 0”。

在2020年的其他日期,例如2020年1月2日执行以上SQL时,SQL语句如下:

SELECT concat('20190808' >= '2020-01-01' , ' ', '20190808' < '2020-01-02');

前一个条件不满足,执行结果为“0 1”。

因此当通过“trans_date >= [前一天日期,格式:yyyy-MM-dd] AND trans_date < [当天日期,格式:yyyy-MM-dd]”条件,从数据库查找前一天的交易时,若交易日期字段格式为“yyyyMMdd”,当且仅当跨年后的第一天,能查询到上一年的全部交易数据。

以上数据库表中的交易日期字段中包含了“yyyy-MM-dd”与“yyyyMMdd”两种格式的数据,前一种格式的交易数据可以每天正常生成前一天的交易记录,后一种格式的交易数据只有在跨年后的第一天能生成前一年全年的交易记录。

3. 问题总结

对于数据库表中的代表交易日期的字段(类型为字符串),应当避免同一个字段包含不同日期格式的数据。假如由于历史原因,确实包含了不同日期格式的数据,在数据库语句的条件中,应当指定是否包含“-”,明确查询的数据格式,避免出现类似的错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值