MySQL - поле ограничения до 5 максимальных вхождений - PullRequest
0 голосов
/ 20 ноября 2018

Справочная информация:

Я использую платформу, которая позволяет пользователям следить за создателями и просматривать их содержимое.

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

Проблема:

Если один создательпользуется особой популярностью (высокий popularity), первые 50 сообщений будут возвращены почти всеми от этого создателя.

Это искажает результаты, так как в идеале 50 возвращенных сообщений не будут в пользу одного конкретного автора.

Вопрос:

Как я могу ограничитьпоэтому автор (который использует поле posted_by) возвращается не более 5 раз .Может быть меньше, но определенно не более 5 раз, если один конкретный автор будет возвращен.

Это все равно должно быть окончательно заказано popularity DESC

SELECT * 
FROM   `source_posts` 
WHERE  `posted_by` IN (SELECT `username` 
                       FROM   `source_accounts` 
                       WHERE  `id` IN (SELECT `sourceid` 
                                       FROM   `user_source_accounts` 
                                       WHERE  `profileid` = '100')) 
       AND `id` NOT IN (SELECT `postid` 
                        FROM   `user_posts_removed` 
                        WHERE  `profileid` = '100') 
       AND `live` = '1' 
       AND `added` >= Date_sub(Now(), INTERVAL 1 month) 
       AND `popularity` > 1 
ORDER  BY `popularity` DESC 
LIMIT  50 

Спасибо.

Редактировать :

Я использую MySQL версии 5.7.24, поэтому, к сожалению, функция row_number () не будет работать в этом случае.

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Можно попробовать функцию номера строки.Используя это, он назначит каждому сотруднику отдельный «идентификатор».Таким образом, если бы у одного сотрудника было 50 записей, будут возвращены только те, чей row_number (названный «rank») меньше или равен 5.

Select *
from(   
 SELECT `source_posts.*`, row_number() over (partition by `username` order by `popularity` desc) as rank
    FROM   `source_posts` 
    WHERE  `posted_by` IN (SELECT `username` 
                           FROM   `source_accounts` 
                           WHERE  `id` IN (SELECT `sourceid` 
                                           FROM   `user_source_accounts` 
                                           WHERE  `profileid` = '100')) 
           AND `id` NOT IN (SELECT `postid` 
                            FROM   `user_posts_removed` 
                            WHERE  `profileid` = '100') 
           AND `live` = '1' 
           AND `added` >= Date_sub(Now(), INTERVAL 1 month) 
           AND `popularity` > 1 
    ORDER  BY `popularity` DESC 
    LIMIT  50 `enter code here`)
where rank <= 5
0 голосов
/ 20 ноября 2018

В MySQL 8+ вы просто используете row_number():

select sp.*
from (select sp.*,
             row_number() over (partition by posted_by order by popularity desc) as seqnum
      from source_posts sp
     ) sp
where seqnum <= 5
order by popularity desc
limit 50;

Я не уверен, что делает остальная часть вашего запроса, потому что он не описан в вашем вопросе.Конечно, вы можете добавить дополнительные критерии фильтрации или join s.

EDIT:

В более ранних версиях вы можете использовать переменные:

select sp.*
from (select sp.*,
             (@rn := if(@p = posted_by, @rn + 1,
                        if(@p := posted_by, 1, 1)
                       )
             ) as rn
      from (select sp.*
            from source_posts sp
            order by posted_by, popularity desc
           ) sp cross join
           (select @p := '', @rn := 0) params
     ) sp
where rn <= 5
order by popularity desc
limit 50;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...