2016-03-28 2 views
3

У меня есть этот SQL-запрос прямо сейчас;Показать 5 записей в базе данных, основанных на дате

SELECT * FROM `articles` WHERE 
`type` = 'press' AND (`published` = '1' AND `time_start` >= '".$time_today."') 
ORDER BY `time_start` ASC, `id` DESC LIMIT 5 

Идея состоит в том, что всегда показываются 5 статей. time_start - время начала, time_end - это время окончания (только PHP mktime).

В основном это записи календаря, только записи, начинающиеся с завтрашнего дня, должны отображаться (работают) и только первые ближайшие пять. Прямо сейчас, есть менее пяти предстоящих календарных точек.

Как это обычно доехать, сделай этот запрос if num_rows > 5, else fill up with older ones? Должен ли я искать резервную копию PHP, просто переписывая данные другим запросом (показывающим 5 «новейших» статей) или есть способ работать с этим в самом запросе?

Вопрос не столько о том, как это могло быть сделано, как ищет правильный способ сделать это, надеюсь, что это не противоречит правилам

+0

используйте этот ЗАКАЗ BY 'time_start' DESC,' id' DESC LIMIT 0,5 –

ответ

1

Так что, похоже, вы хотите, чтобы окно из 5 событий начиналось с начала .. с ним показываются предыдущие события в случае, когда меньше ожиданий.

Два жизнеспособные варианты здесь ..

Если вы счастливы дело с этим в логике приложения:

Run:

SELECT * 
    FROM articles 
    WHERE type = press 
    AND published = '1' 
    AND time_start >= :time_today 
ORDER BY time_start ASC, id ASC /* 'I thought id should be ascending here */ 
    LIMIT 5 

Вычислить, сколько дополнительных статей вам все еще нужно и затем запустить:

SELECT * 
    FROM articles 
    WHERE type = press 
    AND published = '1' 
    AND time_start < :time_today 
ORDER BY time_start DESC, id DESC 
    LIMIT :slack 

Просто отмените первый результирующий набор и добавьте второй к нему и продолжайте движение.

Если вы хотите сделать это все в БД я бы, наверное, сделать:

SELECT * 
    FROM ((
     SELECT * 
     FROM articles 
     WHERE type = press 
     AND published = '1' 
     AND time_start >= :time_today 
    ORDER BY time_start ASC, id ASC 
     LIMIT 5 
      ) 
    UNION ALL 
      (
     SELECT * 
     FROM articles 
     WHERE type = press 
     AND published = '1' 
     AND time_start < :time_today 
    ORDER BY time_start DESC, id DESC 
     LIMIT 5 
     )) window_extents 
ORDER BY time_start DESC, id DESC 
    LIMIT 5 

Это работает путем выбора всех возможных записей для окна, а затем сузить результаты. Он также должен хорошо использовать ваши индексы.

N.B. Похоже, вы увязываете дату в запросе, а не привязываете его. Я бы выбрался из привычки делать это даже в безопасной среде, если это абсолютно необходимо.

0

Просто упорядочивать по TIME_START, а затем сделать предел 5. Так что определенно вы получите 5 строк и в зависимости от времени в то время, которое больше, чем вы указываете в состоянии.

(При условии, у вас есть 5 записей на любое время после предоставленного времени)

+0

Проблема в том, что ему нужно показать первый из «сейчас» и 4, который после этого. Идея состоит в том, что в обзоре будет представлено около 40-50 различных элементов, но они не актуальны для выделенных на главной странице ... – Ieuan

0
SELECT date1, 
    IF((unix_timestamp(date1) - unix_timestamp()) > 0, 1, 0) as a, 
    IF((unix_timestamp(date1) - unix_timestamp()) > 0, (unix_timestamp(date1) - unix_timestamp())/10000000, unix_timestamp(date1) - unix_timestamp()) as b 
FROM `test1` WHERE 1 order by a desc, b desc limit 0,5 

Вы должны пойти с PHP альтернативного запросом, но если вы хотите, вы можете использовать что-то вроде этого. Говоря TS, если дата в будущем мы разделим ее на большое число, чтобы она была близка к 0, мы можем сравнивать/приоритизировать их из TS в прошлом. Это ужасно, я знаю, но уродливый - это весело. Вы должны добавить тест и заменить unix_timestamp() на $ my_now_timestamp и добавить некоторое условие производительности в тест, чтобы избежать разбора всей таблицы ...

0

Просто удалите условие TIME_START из которого условие (AND TIME_START >= '".$time_today."'), и вы должны немного изменить свой заказ на части что-то вроде ниже запроса

SELECT * 
FROM `articles` 
WHERE `type` = 'press' 
    AND `published` = '1' 
ORDER BY 
    CASE WHEN `time_start` >= '".$time_today."' 
     THEN 0 ELSE 1 END ASC, 
    CASE WHEN `time_start` >= '".$time_today."' 
     THEN `time_start` END ASC, 
    CASE WHEN `time_start` < '".$time_today."' 
     THEN `time_start` END DESC LIMIT 5 

Если нет 5 записей после указанной даты, вы должны получить предыдущую запись, чтобы получить счет № 5. Так что нужно удалить проверку даты.

Или вы можете попробовать этот подзапрос также,

SELECT * 
FROM ( 
    SELECT *,(CASE WHEN `time_start` >= '".$time_today."' 
       THEN 0 ELSE 1 END) oflag 
    FROM `articles` 
    WHERE `type` = 'press' 
     AND `published` = '1' 
) T 
ORDER BY 
     oflag ASC, 
     CASE WHEN oflag = 0 THEN `time_start` END ASC, 
     CASE WHEN oflag = 1 THEN `time_start` END DESC LIMIT 5 
0

Ваш запрос должен быть:

SELECT * FROM `articles` 
WHERE `type` = 'press' AND `published` = '1' 
AND `time_start` <= DATEADD(NOW(), INTERVAL 1 DAY) 
ORDER BY `time_start` DESC LIMIT 5 

вы получите пять результатов в порядке убывания time_start поля. Это лучшее решение, так как вам всегда нужно получать из базы данных 5 новых статей, которые начинаются 24 часа с NOW(). Даже если в базе данных нет записей с датами завтрашнего дня для type=press, тогда 5 из более старых в порядке убывания даты будут результатом запроса, что тоже нужно.

Смежные вопросы