Как я могу считать суммированные строки как одну строку в LIMIT?

0

Я хочу выбрать уведомления пользователей в соответствии с этими правилами:

  • все непрочитанные уведомления
  • всегда 2 прочитанных уведомления
  • не менее 15 уведомлений (по умолчанию)

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

( SELECT id FROM events             -- all unread messages
  WHERE author_id = ? AND seen = 0  
) UNION
( SELECT id FROM events             -- 2 read messages
  WHERE author_id = ? AND seen <> 0
  ORDER BY date_time desc
  LIMIT 2                              
) UNION
( SELECT id FROM events             -- at least 15 rows by default
  WHERE author_id = ?
  ORDER BY seen, date_time desc
  LIMIT 15   
) 

И затем я выбираю сопоставленные идентификаторы в запросе выше плюс другую информацию, подобную этой: (Я не хочу комбинировать эти два запроса из-за некоторых причин в действительности)

SELECT SUM(score) score, post_id, title, content, date_time
FROM events
GROUP BY post_id, title, content, date_time
ORDER BY seen, MAX(date_time) desc
WHERE id IN ($ids)

Он работает и все в порядке.


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

Думаю, я должен добавить, что SUM() также в первом запросе? И что GROUP BY? Любая идея?


Пример проблемы, если пользователь заработал 15 приоритетов, первый запрос выбирает их как 15 уведомлений, а второй запрос делает это одним из уведомлений. Как я могу получить 15 разделенных уведомлений? (уведомление, которое будет суммировано во втором запросе, должно учитываться как одно уведомление в первом запросе, как?)

  • 0
    структура таблицы с примерами данных (предоставьте sqlfiddle.com) и ожидаемый результат в виде таблицы данных ascii скажет нам гораздо больше, чем запрос и объяснение проблемы.
  • 0
    @RaymondNijland Все еще не достаточно ясно? Я снова спросил его после улучшения.
Показать ещё 17 комментариев
Теги:

2 ответа

1
Лучший ответ

Поскольку вы, наконец, хотите 15 строк на группу, у вас должны быть правила по группам, а не по сообщениям, на мой взгляд.

Вы можете агрегировать свои данные для каждой группы, а затем проверить, должна ли группа быть в ваших результатах. Вы сделали бы это в предложении HAVING с условной агрегацией, то есть функцией агрегации, используемой для условного выражения. Это один из способов подсчета непрочитанных сообщений, например:

SUM(CASE WHEN seen = 0 THEN 1 ELSE 0 END)

Это другое:

COUNT(CASE WHEN seen = 0 THEN 1 END)

(Филиал ELSE опущен и по умолчанию имеет значение null, которое не считается.)

В MySQL эти выражения еще проще, поскольку false равно 0, а true равно 1. Таким образом, в MySQL вы рассчитываете:

SUM(seen = 0)

Вы также можете использовать другие функции агрегации:

HAVING MAX(seen = 0) = 0 -- no unread messages

HAVING MIN(seen = 0) = 1 -- no read messages

Теперь позвольте выбрать все группы с хотя бы одним непрочитанным сообщением:

SELECT SUM(score) AS score, post_id, title, content, date_time
FROM events
GROUP BY post_id, title, content, date_time
HAVING SUM(seen = 0) > 0;

(Мы также можем использовать HAVING MAX(seen = 0) = 1)

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

(
  SELECT SUM(score) AS score, post_id, title, content, date_time, SUM(seen = 0) as unread
  FROM events
  GROUP BY post_id, title, content, date_time
  HAVING SUM(seen = 0) > 0
)
UNION
(
  SELECT SUM(score) AS score, post_id, title, content, date_time, SUM(seen = 0) as unread
  FROM events
  GROUP BY post_id, title, content, date_time
  ORDER BY SUM(seen = 0) DESC, date_time DESC
  LIMIT 15
)
ORDER BY (unread = 0), date_time DESC;

Если вам нужны одиночные идентификаторы для вышеуказанных групп, используйте IN:

SELECT id
FROM events
WHERE (post_id, title, content, date_time) IN
(
  SELECT post_id, title, content, date_time
  FROM (<above query>) q
);
  • 0
    Спасибо, кажется хорошим, только одно, я не понимаю этого правила: «давайте выберем все группы, по крайней мере, с одним непрочитанным сообщением» , почему, по крайней мере, одно непрочитанное сообщение? Мы должны выбрать все непрочитанные и как минимум два прочитанных.
  • 0
    Какое групповое правило вы бы указали, чтобы рассматривать все непрочитанные сообщения? Если я выберу все группы, в которых есть хотя бы одно непрочитанное сообщение, я рассмотрю все непрочитанные сообщения. Что касается правила: «хотя бы два прочитанных сообщения», я до сих пор не знаю, для чего это правило полезно. Можете ли вы сделать групповую роль для этого? Подойдет ли вам «по крайней мере две группы с хотя бы одним прочитанным сообщением»? Затем добавьте такой запрос с помощью UNION .
Показать ещё 13 комментариев
1

Это не ответ, но слишком длинный для комментария:

Вы думаете, что правила все понятны, но так ли? Скажите, что это не по крайней мере 15, но только по крайней мере 5 строк, которые вы хотите получить в своих окончательных результатах. Из следующей таблицы вам нужны идентификаторы 1, 2, 3 и 4, потому что они непрочитаны. А что насчет остальных?

id | score | post_id | title | content | date_time           | seen
---+-------+---------+-------+---------+---------------------+-----
1  |    10 |      11 | hello | it me | 2018-01-11 12:34:56 |    0
2  |    20 |      22 | hello | it me | 2018-01-12 12:34:56 |    0
3  |    30 |      33 | hello | it me | 2018-01-13 12:34:56 |    0
4  |    40 |      44 | hello | it me | 2018-01-14 12:34:56 |    0
5  |    50 |      11 | hello | it me | 2018-01-11 12:34:56 |    1
6  |    60 |      22 | hello | it me | 2018-01-12 12:34:56 |    1
7  |    70 |      44 | hello | it me | 2018-01-14 12:34:56 |    1
8  |    80 |      55 | hello | it me | 2018-01-05 12:34:56 |    1
9  |    90 |      55 | hello | it me | 2018-01-05 12:34:56 |    1

Имеет ли значение, что есть уведомления для чтения для тех же групп? Имеет ли значение, что они новее, чем уведомления 8 и 9? Или вы просто добавите ID 8 (или 9?) В набор и сделаете это?

Независимо от того, выбираете ли вы идентификаторы 1, 2, 3, 4 и говорите 8 или вы выбираете все строки, вы получите пять групп. Поэтому, пожалуйста, сообщите нам, какие идентификаторы вы выберете и почему.

  • 0
    Теперь я понимаю, я даже не знаю, чего я хочу :-(
  • 0
    Upvote BW .....
Показать ещё 19 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню