Ваш подход в порядке, но ваш запрос - нет.В частности, MySQL не гарантирует порядок вычисления выражений в SELECT
, поэтому вам не следует присваивать переменную в одном выражении и использовать ее в другом.
К счастью, вы можете объединять присваивания водиночное выражение:
SELECT b.*
FROM (SELECT b.sub_cat_id, b.title, created_date
(@rn := IF(@sc = b.sub_cat_id, @rn + 1,
if(@sc := b.sub_cat_id, 1, 1)
)
) as rn
FROM blog b CROSS JOIN
(SELECT @sc := -1, @rn := 0) params
WHERE b.type = 'BLOG' AND
b.sub_cat_id IN (1, 2, 8) AND
b.created_date <= NOW() -- is this really needed?
ORDER BY b.sub_cat_id DESC, b.created_date DESC) AS records
) b
WHERE rn <= 6;
Для этого запроса вам нужны индексы.Я думаю, что это будет работать: type, sub_cat_id, created_date)
.К сожалению, group by
все еще потребует сортировки данных.В более поздних версиях MySQL, я думаю, вам нужно выполнить сортировку в подзапросе, а затем присваивать rn
.
Мне интересно, можно ли сделать эту формулировку более эффективной:
select b.*
from blogs b
where b.type = 'BLOG' and
b.sub_cat_id in (1, 2, 8) and
b.created_at >= (select b2.created_at
from blogs b2
where b2.type = b.type and
b2.sub_cat_id = b.sub_cat_id
order by b2.created_at desc
limit 1 offset 5
);
Для этого вам нужен индекс для blog(type, sub_cat_id, created_at)
.