Почему не работает этот простой оператор SQL? - PullRequest
3 голосов
/ 25 декабря 2009

dateposted - это столбец MySQL TIMESTAMP:

 SELECT * 
   FROM posts 
  WHERE dateposted > NOW() - 604800

... СЛЕДУЕТ , если я не ошибаюсь, вернуть строки, где dateposted было на прошлой неделе. Но он возвращает только сообщения менее чем за один день. У меня сложилось впечатление, что TIMESTAMP использовал секунды?

IE: 7 *3600* 24 = 604800

Ответы [ 5 ]

13 голосов
/ 25 декабря 2009

Использование:

WHERE dateposted BETWEEN DATE_ADD(NOW(), INTERVAL -7 DAY) AND NOW()
4 голосов
/ 25 декабря 2009

Это потому, что now() неявно преобразуется в число из метки времени, а правила преобразования mysql создают число, подобное YYYYMMDDHHMMSS.uuuuuu

из документации MySQL:

mysql> SELECT NOW();
        -> '2007-12-15 23:50:26'
mysql> SELECT NOW() + 0;
        -> 20071215235026.000000
2 голосов
/ 25 декабря 2009

Внутренне возможно. Способ сделать это - математические функции даты. Так было бы:

SELECT * FROM posts WHERE dateposted > DATE_ADD(NOW(), INTERVAL -7 DAY)

Я думаю, что есть DATE_SUB, я просто привык везде использовать ADD.

2 голосов
/ 25 декабря 2009

Нет, вы не можете неявно использовать целочисленную арифметику с TIMESTAMP, DATETIME и другими типами данных, связанных с датами. Вы думаете о формате метки времени UNIX, который представляет собой целое число секунд с 1 января 1970 года.

Вы можете преобразовать типы данных SQL в метку времени UNIX в MySQL, а затем использовать арифметику:

SELECT * FROM posts WHERE UNIX_TIMESTAMP(dateposted)+604800 > NOW()+0;

Примечание: добавление нуля к NOW() заставляет его возвращать числовое значение вместо строкового значения.


обновление: Хорошо, я совершенно не согласен с вышеуказанным запросом. Преобразование NOW() в числовой вывод не дает число, которое можно сравнить с метками времени UNIX. Это производит число, но число не считает секунды или что-нибудь еще. Цифры просто соединены вместе YYYYMMDDHHMMSS.

* * 1 022 Пример: * 1 023 *
CREATE TABLE foo (
  id SERIAL PRIMARY KEY,
  dateposted TIMESTAMP
);

INSERT INTO foo (dateposted) VALUES ('2009-12-4'), ('2009-12-11'), ('2009-12-18');

SELECT * FROM foo;

+----+---------------------+
| id | dateposted          |
+----+---------------------+
|  1 | 2009-12-04 00:00:00 |
|  2 | 2009-12-11 00:00:00 |
|  3 | 2009-12-18 00:00:00 |
+----+---------------------+

SELECT *, UNIX_TIMESTAMP(dateposted) AS ut, NOW()-604800 AS wk FROM foo

+----+---------------------+------------+-----------------------+
| id | dateposted          | ut         | wk                    |
+----+---------------------+------------+-----------------------+
|  1 | 2009-12-04 00:00:00 | 1259913600 | 20091223539359.000000 |
|  2 | 2009-12-11 00:00:00 | 1260518400 | 20091223539359.000000 |
|  3 | 2009-12-18 00:00:00 | 1261123200 | 20091223539359.000000 |
+----+---------------------+------------+-----------------------+

Понятно, что числовые значения несопоставимы. Однако UNIX_TIMSTAMP() также может преобразовывать числовые значения в этом формате, поскольку он может преобразовывать строковое представление временной метки:

SELECT *, UNIX_TIMESTAMP(dateposted) AS ut, UNIX_TIMESTAMP(NOW())-604800 AS wk FROM foo

+----+---------------------+------------+------------+
| id | dateposted          | ut         | wk         |
+----+---------------------+------------+------------+
|  1 | 2009-12-04 00:00:00 | 1259913600 | 1261089774 |
|  2 | 2009-12-11 00:00:00 | 1260518400 | 1261089774 |
|  3 | 2009-12-18 00:00:00 | 1261123200 | 1261089774 |
+----+---------------------+------------+------------+

Теперь можно выполнить запрос с выражением, сравнивающим их:

SELECT * FROM foo WHERE UNIX_TIMESTAMP(dateposted) > UNIX_TIMESTAMP(NOW())-604800

+----+---------------------+
| id | dateposted          |
+----+---------------------+
|  3 | 2009-12-18 00:00:00 |
+----+---------------------+

Но ответ, данный @OMGPonies, все же лучше, потому что это выражение в моем запросе, вероятно, не может использовать индекс. Я просто предлагаю это как объяснение того, как работают функции TIMESTAMP и NOW().

1 голос
/ 25 декабря 2009

Попробуйте этот запрос:

SELECT * FROM posts WHERE DATE_SUB(CURDATE(),INTERVAL 7 DAY) < dateposted;

Я предполагаю, что вы используете mySQL.

...