如何比较mysql中格式为dd.mm.yyyy的日期(varchar)?

csbfibhn  于 2021-06-21  发布在  Mysql
关注(0)|答案(3)|浏览(420)

我希望能够选择mysql数据库中两个日期之间的所有日期,其中日期是格式为dd.mm.yyyy的varchar。

Database
date (varchar) | value
------------------------
31.01.2018     | 123
------------------------
28.02.2018     | 456

这行不通

Query
SELECT date,value from Database WHERE date BETWEEN '2018-01-01' AND '2018-01-31'

我知道我需要 WHERE date LIKE '%.01.2018' 整整几个月,但这还不够。
我可以用php来做这个,但不想这样做,因为那样会花太长时间。我想我可以用 CAST 功能,但不确定如何。
在mysql中最好的方法是什么?

wz1wpwve

wz1wpwve1#

你可以选择revo的解决方案,或者,这个

SELECT date,value from Database WHERE (not (date is null)) and CHAR_LENGTH(date) = 10 (CONCAT(SUBSTRING(date, 7), '-', SUBSTRING(date, 4, 2), '-', SUBSTRING(date, 1, 2))) BETWEEN '2018-01-01' AND '2018-01-31'

在这里,我们检查date是否不为null以及是否为所需的长度,这样当程序遇到非常规值时就不会崩溃。

vd2z7a6w

vd2z7a6w2#

你可以用 STR_TO_DATE() :

WHERE STR_TO_DATE(date, '%d.%m.%Y') BETWEEN '2018-01-01' AND '2018-01-31'
rqqzpn5f

rqqzpn5f3#

在mysql中,最好的方法是避免将日期存储为dd.mm.yyyy格式的字符串。相反,把日期储存在适当的地方 DATE 列,因此它们匹配本机格式:yyyy-mm-dd。
使用的解决方案 STR_TO_DATE() 或者其他函数意味着不能使用索引来优化比较。搜索将以较差的性能运行,因为它必须执行表扫描。
请回复您的意见:
200万行不是一个大表。重组不应该超过一两分钟。如果你等到table变大的时候,事情只会变得更难。
由于您的数据格式错误,因此不能仅更改数据类型。下面是我将如何解决这个问题:
步骤1:添加一个新列,该列是正确的 DATE 数据类型:

ALTER TABLE MyTable ADD COLUMN myDate DATE;

(顺便说一下,不要将表命名为“database”或列命名为“date”。这些都是保留字,无论如何都不是描述性的。你把程序变量命名为“variable”吗
第2步:创建触发器,以便应用程序对旧列的使用自动复制到新列:

CREATE TRIGGER InsMyDate BEFORE INSERT ON MyTable
FOR EACH ROW 
SET NEW.myDate = COALESCE(NEW.myDate, STR_TO_DATE(NEW.oldDate, '%d.%m.%Y'));

CREATE TRIGGER UpdMyDate BEFORE UPDATE ON MyTable
FOR EACH ROW 
SET NEW.myDate = COALESCE(NEW.myDate, STR_TO_DATE(NEW.oldDate, '%d.%m.%Y'));

联合的原因一会儿就会清楚。
步骤3:回填过去行中的所有值:

UPDATE MyTable
SET myDate = STR_TO_DATE(NEW.oldDate, '%d.%m.%Y')
WHERE myDate IS NULL;

你只需要做一次。创建触发器后,插入的任何新行都将自动将正确的日期值复制到新列。在创建触发器之前插入的任何行在新列中都将为null,因此需要如上所示更新它们。
第4步:更改应用程序代码,以便任何对旧的错误日期列的引用都使用新的日期列。地址引用日期的任何插入、更新或选择。测试并部署此代码更改。
执行此操作后,任何insert或update都将在new date列中指定一个值,而不是null。这将使触发器有效地成为no op,因为mydate中的非null值将优先于str\u to\u date()表达式。这允许您在方便的时候部署代码,而数据库将继续对您的数据执行正确的操作。
步骤5:删除触发器和旧字符串日期列:

DROP TRIGGER InsMyDate;
DROP TRIGGER UpdMyDate;
ALTER TABLE MyTable DROP COLUMN oldDate;

如果您担心在表重组期间每个alter表都会锁定表,那么应该学习使用pt online schema change。这允许您在不锁定的情况下执行alter表(除了重组结束时的短暂时刻)。

相关问题