Как сравнить даты (varchar), отформатированные как dd.mm.yyyy в MySQL? - PullRequest
0 голосов
/ 11 июня 2018

Я бы хотел иметь возможность выбирать все даты между двумя датами в базе данных MySQL, где даты являются типом в формате dd.mm.yyyy.

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?

Ответы [ 3 ]

0 голосов
/ 11 июня 2018

Вы можете выбрать решение 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'

Здесь мы проверяем, чтобы дата не была нулевой и имела требуемую длину, чтобы ваша программа не вылетала, когда она встречается с нетрадиционными значениями..

0 голосов
/ 11 июня 2018

Лучший способ сделать это в MySQL - избегать хранения дат в виде строки в формате DD.MM.YYYY.Вместо этого сохраняйте даты в надлежащих столбцах DATE, чтобы они соответствовали собственному формату: ГГГГ-ММ-ДД.

Решения использования STR_TO_DATE() или других функций означают, что вы не можете использовать индекс для оптимизациисравнения.Поиск будет выполняться с низкой производительностью, поскольку он должен выполнить сканирование таблицы.


Ваш комментарий:

2 миллиона строк - это не большая таблица.Это не должно занять больше минуты или двух, чтобы реструктурировать его.Это будет только сложнее, если вы будете ждать, пока таблица не станет больше.

Поскольку ваши данные имеют неправильный формат, вы не можете просто изменить тип данных.Вот как я могу это исправить:

Шаг 1: Добавить новый столбец с правильным DATE типом данных:

ALTER TABLE MyTable ADD COLUMN myDate DATE;

( ByКстати, не называйте свою таблицу «База данных» или столбец «дата». Это зарезервированные слова, и в любом случае они не являются описательными. Вы называете программные переменные «переменная»? )

Шаг 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'));

Причина COALESCE будет понятна через мгновение.

Шаг 3: Заполните все значения в прошлых строках:

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

Это нужно сделать только один раз.Все новые вставленные строки будут автоматически копировать правильное значение даты в новый столбец после создания триггеров.Любые строки, вставленные до того, как вы создали триггеры, будут иметь значение NULL в новом столбце, поэтому вам нужно ОБНОВИТЬ их, как показано выше.

Шаг 4: Измените код приложения, чтобы любая ссылка настарый неправильный столбец даты использует новый столбец даты.Обращайтесь к любому INSERT, UPDATE или SELECT, который ссылается на дату.Протестируйте и разверните это изменение кода.

После того, как вы это сделаете, любой INSERT или UPDATE будет указывать значение в новом столбце даты вместо NULL.Это фактически сделает триггер неоперативным, потому что не-NULL-значение в myDate будет иметь приоритет над выражением STR_TO_DATE ().Это позволяет вам развернуть код по вашему усмотрению, и база данных просто будет продолжать делать правильные действия с вашими данными.

Шаг 5: Удалите триггеры и старую строковую датустолбец:

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

Если вы обеспокоены тем, что каждый ALTER TABLE будет блокировать таблицу во время реструктуризации таблицы, вам следует научиться использовать pt-online-schema-change .Это позволяет вам выполнить ALTER TABLE без блокировки (за исключением краткого момента в конце реструктуризации).

0 голосов
/ 11 июня 2018

Вы можете использовать STR_TO_DATE():

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