Смешивание разных категорий результатов, упорядоченных по счету в MySQL - PullRequest
3 голосов
/ 05 июня 2011

В моем PHP-приложении у меня есть таблица статей mysql, в которой есть следующие столбцы:

article_id    articletext    category_id    score

Каждая статья имеет оценку, которая рассчитывается на основе ее популярности и относится к определеннойкатегория (доступно около 10 категорий)

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

article_id    articletext    category_id    score
-----------------------------------------------------
142           <.....>        5              100
153           <.....>        3              97
119           <.....>        5              99
169           <.....>        2              93
121           <.....>        7              89
197           <.....>        2              92
.
.
.

Первое (наивное) решение, которое приходит в голову, - выполнить 10 отборов (1 для каждой категории), упорядочивих по убыванию оценки, а затем на уровне PHP, чередуя каждый возвращенный набор данных, выбирая по одному результату за раз и объединяя их вместе в новом массиве.

Есть ли более эффективный способ добиться этого?Если возможно на уровне MySQL

Ответы [ 3 ]

1 голос
/ 05 июня 2011

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

Если вы получили топ-100, это может удовлетворить требования 90% времени и будет дешевле и быстрее, чем 10 отдельных запросов.

Если бы это был SQL Server, я мог бы помочь больше ...

На самом деле, у меня есть другая идея. Каждые 5 минут запускайте процесс, который вычисляет список и кэширует его в таблице. Сделайте DML для связанных таблиц недействительным кеш, чтобы он не использовался до повторного заполнения (возможно, статья была удалена). Если кеш недействителен, вы можете рассчитывать его на лету ... И все равно можете использовать его для повторного заполнения кеша.

Возможно, стратегически можно обновить кэшированный список, а не пересчитать его. Но это может быть настоящим испытанием.

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

1 голос
/ 05 июня 2011

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

select * from (
(select @r:=@r+1 as rownum,article_id,articletext,category_id,score
from articles,(select @r:=0) as r
where category_id = 1
order by score desc limit 100000000) 
union all
(select @r1:=@r1+1,article_id,articletext,category_id,score
from articles,(select @r1:=0) as r
where category_id = 2
order by score desc limit 100000000)
union all
(select @r2:=@r2+1,article_id,articletext,category_id,score
from articles,(select @r2:=0) as r
where category_id = 3
order by score desc limit 100000000)
) as t
order by rownum,score desc
0 голосов
/ 05 июня 2011

Ваше наивное решение - именно то, что я бы сделал.

...