Группировка и сортировка вопроса
У меня есть система уведомлений (на основе PHP, MySQL), и я пытаюсь сделать следующее: Результаты уведомлений о запросах сгруппированы по сообщениям без каких-либо ограничений, но затем упорядочены по time_sent, ограниченному 5 (для каждой итерации). Затем я использовал ajax, чтобы показать следующий набор итераций из 5 уведомлений.
В основном мне нужно 5 уведомлений за раз (за набор), но для каждого из них, если группа касается одного сообщения: может быть столько уведомлений, сколько нужно:
Вот как там будет отображаться:
- Уведомление о сообщении F - отправлено 1 день назад
- Первое уведомление о посте C - отправлено 2 дня назад
- Второе уведомление о посте C - отправлено 3 дня назад
- Третье уведомление о посте C - отправлено 4 дня назад
- Четвертое уведомление о посте C - отправлено 5 дней назад
- Уведомление о посте Y - отправлено 3 дня назад
- Первое уведомление о посте D - отправлено 4 дня назад
- Второе уведомление о посте D - отправлено 5 дней назад
- Третье уведомление о посте D - отправлено 6 дней назад
- Уведомление о посте Y - отправлено 5 дней назад
Если бы новое сообщение было отправлено в отношении сообщения Y, оно, естественно, было бы поднято вверх по списку.
Вот как я начал, прежде чем решил внедрить эту групповую систему:
$notifications_req = mysql_query('SELECT * FROM notifications WHERE user_id = "'.$user_id.'" ORDER BY time_sent DESC LIMIT 5');
А теперь я заблудился и боролся с этой группой по порядку и по логике.
База данных содержит, конечно, post_id
колонка.
РЕДАКТИРОВАТЬ:
В итоге я довольно резко изменил способ сортировки уведомлений. Вот как я в итоге это сделал. Это может быть не самым эффективным, но работает так, как я хочу:
<?php $notifications_all_req = mysql_query('SELECT * FROM notifications WHERE user_id = "'.$user_id.'" ORDER BY time_sent DESC'); if(mysql_num_rows($notifications_all_req) > 0){
while($row = mysql_fetch_assoc($notifications_all_req))
{
$post_req_ids[] = $row['post_id'];
}
$unique_post_ids = array_unique($post_req_ids);
foreach ($unique_post_ids as $i => $unique_post_id)
{
?>
<ul id="notifications_ul_<?php echo $i; ?>">
<?php
$notifications_req = mysql_query('SELECT * FROM notifications WHERE (user_id = "'.$user_id.'" AND post_id = "'.$unique_post_id.'") ORDER BY time_sent DESC ');
while($notification = mysql_fetch_assoc($notifications_req))
{
}
?>
</ul>
<?php
} } ?>
Таким образом, я могу контролировать пределы обеих групп уведомлений (используя $i
) и те, что в каждой группе, также с Ajax загружают больше кода для последней.
1 ответ
Вы не хотите использовать GROUP BY
здесь, потому что это для сводных запросов.
Совет: не используйте SELECT *
, Вместо этого выберите нужные столбцы по имени.
Совет профессионала: люди советуют вам использовать PDO или mysqli_ по очень веской причине. Интерфейс mysql_ небезопасен. Если вы поместите веб-приложение, основанное на mysql_, в общедоступной сети, вам придет в голову какой-нибудь злодей. Если вы не возражаете против того, чтобы вас забили, например, если вы создаете прототип или веб-сайт с проверкой концепции, не беспокойтесь об этом.
Давайте получим порядок набора результатов прямо перед тем, как начнем сегментировать его на пять столбцов. Вам нужно два предмета в вашем ORDER BY
пункт. Кажется, вы хотите, чтобы ваш набор результатов был упорядочен следующим образом.
SELECT *
FROM notifications
WHERE user_id = ?
ORDER BY post_id, time_sent DESC
Попробуйте, без LIMIT 5
и отладьте ваш php-код, чтобы вы получили хорошее отображение, даже если оно слишком длинное для ваших целей.
Далее, если я вас правильно понимаю, вы пытаетесь показывать пять сообщений одновременно. Это становится сложнее, потому что вы хотите пять сообщений, и каждая из них может иметь различное количество уведомлений.
Таким образом, мы должны найти способ получать пять сообщений одновременно. Этот подзапрос сделает это, предоставив список из пяти значений post_id.
SELECT DISTINCT post_id
FROM notifications
WHERE user_id = ?
ORDER BY post_id
LIMIT 5 OFFSET ?
Параметр для OFFSET ?
должно быть 0, 5, 10 и т. д., чтобы получить первый, второй, третий и т. д. пакет из пяти сообщений. Если вы хотите только первые пять постов, просто опустите OFFSET
пункт.
Теперь нам нужно внедрить этот подзапрос, который получает только пять сообщений в другом запросе, чтобы получить все данные. Это работает так.
SELECT *
FROM notifications
WHERE post_id IN (
SELECT DISTINCT post_id
FROM notifications
WHERE user_id = ?
ORDER BY post_id
LIMIT 5 OFFSET ?
)
ORDER BY post_id, time_sent DESC
Этот последний, более сложный SQL-запрос даст набор результатов, который выглядит как первый оператор. Вы должны иметь возможность подключить его к отлаженному php-коду и получить нужный вам дисплей.