Ответ 1
Вы можете использовать STR_TO_DATE().
В настоящее время я разрабатываю приложение, которое отображает документы и позволяет членам выполнять поиск этих документов по нескольким параметрам, одним из которых является диапазон дат.
Проблема, с которой я столкнулась, заключается в том, что сама схема базы данных не была разработана мной, а создатель базы данных создал таблицу "date" с полями "день", "месяц", "год".
Я хотел бы знать, как я могу выбрать определенный день, месяц, год из таблицы и создать объект даты в SQL, чтобы я мог сравнивать даты, вводимые пользователем с помощью BETWEEN.
Ниже представлена структура таблицы даты:
CREATE TABLE IF NOT EXISTS `date` (
`deposition_id` varchar(11) NOT NULL default '',
`day` int(2) default NULL,
`month` int(2) default NULL,
`year` int(4) default NULL,
PRIMARY KEY (`deposition_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Вы можете использовать STR_TO_DATE().
Когда у вас есть целочисленные значения за год, месяц и день, вы можете сделать DATETIME, объединив MAKEDATE() и DATE_ADD(). MAKEDATE() с постоянным днем 1 даст вам DATETIME в течение первого дня данного года, а затем вы можете добавить к нему месяц и день с DATE_ADD():
mysql> SELECT MAKEDATE(2013, 1);
+-------------------+
| MAKEDATE(2013, 1) |
+-------------------+
| 2013-01-01 |
+-------------------+
mysql> SELECT DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH);
+---------------------------------------------------+
| DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH) |
+---------------------------------------------------+
| 2013-03-01 |
+---------------------------------------------------+
mysql> SELECT DATE_ADD(DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH), INTERVAL (11)-1 DAY);
| DATE_ADD(DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH), INTERVAL (11)-1 DAY) |
+----------------------------------------------------------------------------------+
| 2013-03-11 |
+----------------------------------------------------------------------------------+
Итак, чтобы ответить на вопрос OP:
SELECT * FROM `date`
WHERE DATE_ADD(DATE_ADD(MAKEDATE(year, 1), INTERVAL (month)-1 MONTH), INTERVAL (day)-1 DAY)
BETWEEN '2013-01-01' AND '2014-01-01';
Чтобы построить для него отсортированную строку даты, вам понадобится CONCAT
, чтобы объединить биты и LPAD
, чтобы поля месяца и дня составляли две цифры. Что-то вроде этого:
CONCAT(`year`,'-',LPAD(`month`,2,'00'),'-',LPAD(`day`,2,'00'))
После этого вы сможете использовать BETWEEN
, поскольку они будут в отсортированном формате. Однако, если вам все равно нужно преобразовать их в фактические поля datetime, вы можете обернуть все это в UNIX_TIMESTAMP()
, чтобы получить значение временной метки.
Итак, у вас получится что-то вроде этого:
SELECT UNIX_TIMESTAMP(CONCAT(`year`,'-',LPAD(`month`,2,'00'),'-',LPAD(`day`,2,'00'))) as u_date
WHERE u_date BETWEEN timestamp_1 and timestamp_2
Однако имейте в виду, что это будет значительно медленнее, чем если бы поле было просто простой меткой времени. И вы обязательно должны убедиться, что у вас есть индекс в полях год, месяц и день.
Попробуйте использовать CONCAT() и сделайте это одно поле и сравните.
Не уверен, что вы можете сравнить его как дату после конкатенации.
Вы можете сравнить как целое число.
укажите день месяца месяца и сделайте целое число, подобное этому 20101017, и сравните.
Надеюсь:)