$query = "SELECT t.*, p.* FROM topics t, posts p WHERE p.topic_id=t.tid AND t. start_time>".(time()-86400)." AND p.new_post=1";
Последнее условие (p.new_post=1) обеспечивает вывод текста первого сообщения.
Иногда нужно выводить текст не первого сообщения, а сообщения, помеченного вручную (сохраняется в таблице сообщений в поле icon_id). Добавляю условие p.icon_id>0. Запрос:
$query = "SELECT t.*, p.* FROM topics t, posts p WHERE p.topic_id=t.tid AND t. start_time>".(time()-86400)." AND ( p.icon_id>0 OR p.new_post=1 )";
Получаю теперь 2 строки результатов на каждую тему: строка с первым сообщением и строка с помеченным вручную сообщением.
Я конечно могу средствами php отбросить строку с первым сообщением для тех тем, в которых есть помеченные сообщения:
$DB->query($query);
$rowz = array();
while ( $row = $DB->fetch_row() )if( !$rowz[ $row['tid'] ] or $row['icon_id'] > 0 )$rowz[ $row['tid'] ] = $row;
Но логика подсказывает, что грябчить всё что попало из базы, а затем отсеивать лишнее - не продуктивно.
Не соображу как средствами SQL осуществить строгий выбор: если существует p.icon_id>0, то отдавать эту строку, и только если не существует, тогда отдавать строку по условию p.new_post=1.
Спустя 15 минут, 31 секунда (2.08.2012 - 22:40) inpost написал(а):
ORDER BY p.new_post=1 DESC (или ASC) , в таком случае данная запись попадёт в конец по сортировке, а первой будет с p.icon_id, и в конце ещё дописать LIMIT 1, в таком случае p.new_post в сортировке будет последней и выберется лишь в том случае, если она будет последний.
Или ORDER BY FIELD(`p.new_post`,1) . Один из этих вариантов будет верен. Я не помню, будет ли первый вариант работать
Или ORDER BY FIELD(`p.new_post`,1) . Один из этих вариантов будет верен. Я не помню, будет ли первый вариант работать
Спустя 2 часа, 33 минуты, 35 секунд (3.08.2012 - 01:14) FatCat написал(а):
Цитата (inpost @ 3.08.2012 - 00:40) |
ORDER BY p.new_post=1 DESC |
Ты имеешь в виду ORDER BY p.new_post ASC? Это ничего не даст. Это изменит порядок строк, но строки будут те же самые.
Цитата (inpost @ 3.08.2012 - 00:40) |
и в конце ещё дописать LIMIT 1 |
Лимиты там не допишешь. Мы не знаем сколько тем создано за сутки. Нужны все; не нужно двух строк по одной теме.
Спустя 7 часов, 38 минут, 43 секунды (3.08.2012 - 08:52) svs14 написал(а):
не знаю или поможет, но может стоит здесь глянуть.
http://www.mysql.ru/docs/man/Control_flow_functions.html
http://www.mysql.ru/docs/man/Control_flow_functions.html
Спустя 25 минут, 36 секунд (3.08.2012 - 09:18) Placido написал(а):
Не знаю, как насчет оптимальности, но можно "извратиться" таким образом)
$query = "SELECT t.*, p.*
FROM topics t
JOIN posts p ON p.topic_id = t.tid
WHERE t.start_time>".(time()-86400)."
AND IF((SELECT COUNT(*) FROM posts WHERE icon_id > 0) > 0, p.icon_id > 0, p.new_post = 1)";
Спустя 9 минут, 50 секунд (3.08.2012 - 09:28) vagrand написал(а):
тс, никак ты это не сделаеш одним запросом. Тут нужно менять структуру хранения данных или делать два запроса
Спустя 7 минут, 44 секунды (3.08.2012 - 09:36) Placido написал(а):
Цитата (vagrand @ 3.08.2012 - 10:28) |
тс, никак ты это не сделаеш одним запросом. |
Мой запрос доказывает обратное.
Спустя 2 часа, 59 минут, 15 секунд (3.08.2012 - 12:35) vagrand написал(а):
Placido
твой запрос положит бд даже при средних нагрузках
твой запрос положит бд даже при средних нагрузках
Спустя 17 минут, 48 секунд (3.08.2012 - 12:53) Placido написал(а):
Цитата (vagrand @ 3.08.2012 - 13:35) |
Placido твой запрос положит бд даже при средних нагрузках |
Значит, все-таки, можно сделать одним запросом? Это я насчет голословности утверждений типа "никак ты это не сделаеш одним запросом" (sic). Свои слова необходимо хоть чем-то подкреплять. Это, кстати, касается и "положит БД даже при средних нагрузках". При каких нагрузках? С какими индексами? Какую БД и т.д. Где Explain в подтверждение? По поводу спорности оптимальности запроса я сразу написал, я показал только принцип - при желании можно попробовать его оптимизировать (ответом снова будет "никак ты это не оптимизируеШ?").
Спустя 2 часа, 19 секунд (3.08.2012 - 14:53) vagrand написал(а):
Placido
О каких индексах может идти ресь если у тебя в WHERE подзапрос?
О каких индексах может идти ресь если у тебя в WHERE подзапрос?
Спустя 3 часа, 4 минуты, 2 секунды (3.08.2012 - 17:57) Placido написал(а):
Цитата (vagrand @ 3.08.2012 - 15:53) |
Placido О каких индексах может идти ресь если у тебя в WHERE подзапрос? |
И снова ничем не подтвержденное утверждение. Какая проблема в том, что в WHERE подзапрос? Чем это мешает использованию индексов?
Вот EXPLAIN подобного запроса на таблице в 10000 записей:
Время выполнения запроса - 0,016 сек.
Твои аргументы?
Спустя 42 минуты, 56 секунд (3.08.2012 - 18:40) inpost написал(а):
FatCat
Сделай вообще через 2 отдельных запроса. Когда тестировал различные JOIN, то они как-то дубово реализованы в мускуле и в связи с этим 2 отдельных селекта работали быстрее. То есть выборку первую, далее проверяешь через mysql_num_rows, если записи не выбрались - тогда второй запрос.
Сделай вообще через 2 отдельных запроса. Когда тестировал различные JOIN, то они как-то дубово реализованы в мускуле и в связи с этим 2 отдельных селекта работали быстрее. То есть выборку первую, далее проверяешь через mysql_num_rows, если записи не выбрались - тогда второй запрос.
Спустя 1 час, 39 минут, 38 секунд (3.08.2012 - 20:20) FatCat написал(а):
Цитата (vagrand @ 3.08.2012 - 11:28) |
Тут нужно менять структуру хранения данных или делать два запроса |
Насчет структуры хранения замечание дельное. В таблице тем добавить поле, хранящее айдишник сообщения для анонса.
Цитата (inpost @ 3.08.2012 - 20:40) |
Сделай вообще через 2 отдельных запроса |
1 запрос, отдающий 20 строк, мне нравится больше 2 запросов по 10 строк.
Отсортировать массив из 20 ячеек не сложно и средствами php.
_____________
Бесплатному сыру в дырки не заглядывают...