in Профессиональное

Random MySQL date

В этой статье рассмотрим несколько вариантов получения случайной даты в MySQL. Для чего это нужно? Ну к примеру для генерации фикстур и прочих тестовых данных, чтобы были похожи на реальные.


Самый простой вариант – совершенно случайная дата:

mysql> SELECT FROM_UNIXTIME(RAND() * 2147483647) AS `rand`;
+---------------------+
| rand                |
+---------------------+
| 1998-04-01 21:42:48 |
+---------------------+
1 ROW IN SET (0.00 sec)

Попробуем ещё раз?

mysql> SELECT FROM_UNIXTIME(RAND() * 2147483647) AS `rand`;
+---------------------+
| rand                |
+---------------------+
| 2028-03-21 22:44:43 |
+---------------------+
1 ROW IN SET (0.00 sec)

Окей, зачем умножать на 2147483647? (ещё не догадались?! 🙂 Ну тут всё просто, как 2 копейки: 2147483647 это самый большой SIGNED INT32 и по совместительству писарчук самый последний распоследний таймштамп. Проверяется это так (ежели не верите):

Так ещё работает:

mysql> SELECT FROM_UNIXTIME(2147483647) AS `rand`;
+---------------------+
| rand                |
+---------------------+
| 2038-01-18 19:14:07 |
+---------------------+
1 ROW IN SET (0.00 sec)

А если добавим хоть секундочку (2147483648) – уже работать не будет:

mysql> SELECT FROM_UNIXTIME(2147483648) AS `rand`;
+------+
| rand |
+------+
| NULL |
+------+
1 ROW IN SET (0.01 sec)

Таким образом, функция RAND() даёт нам случайное значение в диапазоне от 0 до 1 и умножая его на максимально возможный таймштамп мы получим случайную дату в диапазоне от 1969 до 2038 гг. Но что же нам делать, если требуется дата в некотором строго определённом периоде?

Случайная дата 2011го года

Получается вот так:

mysql> SELECT FROM_UNIXTIME(RAND() * (1325275200 - 1293825600) + 1293825600) AS `the_date`;
+---------------------+
| the_date            |
+---------------------+
| 2011-04-27 05:01:04 |
+---------------------+
1 ROW IN SET (0.00 sec)

Так круто, что хочется попробовать ещё раз 😉

mysql> SELECT FROM_UNIXTIME(RAND() * (1325275200 - 1293825600) + 1293825600) AS `the_date`;
+---------------------+
| the_date            |
+---------------------+
| 2011-08-15 12:54:51 |
+---------------------+
1 ROW IN SET (0.01 sec)

А чо энто было то?

Когда нам нужно зафиксировать диапазон, между start и end датами, и мы имеем случайное значение от 0 до 1 – требуется вычесть из конечного таймштампа начальный end - start, что даст искомый интервал в секундах и “двинуть” интервал в начало периода. Т.о. наша супер-формула выглядит вот так:

(end - start) * RAND + start

Ну и для того чтобы высвободить вам побольше времени для Angry Birds (или чего-то подобного), а также не морщить лоб, пытаясь в уме переводить DATETIME в TIMESTAMP – мы воспользуемся функцией UNIX_TIMESTAMP:

mysql> SELECT
    -> UNIX_TIMESTAMP('2011-01-01') AS START,
    -> UNIX_TIMESTAMP('2011-12-31') AS END;
+------------+------------+
| START      | END        |
+------------+------------+
| 1293825600 | 1325275200 | 	
+------------+------------+
1 ROW IN SET (0.00 sec)

Оригинал для перевода взял тут: http://www.phpied.com/random-mysql-date/

Write a Comment

Comment

*

  1. От себя добавлю, что пользоваться функцией RAND в условиях репликации беззопасно при ROW-based репликации.

    • В данном случае RAND это просто способ получить случайную дату, к примеру для того чтобы заполнить тестовыми данными таблицу. Репликация тут вроде как бы и не нужна… Или нужна?