Это немного уродливо, но вы можете сделать это одним запросом:
SELECT name,
`date`
FROM ( SELECT @rank := @rank + 1 AS rank,
name,
`date`
FROM (SELECT @rank := 0) dummy
JOIN products
ORDER BY `date` DESC, name) dateranked
ORDER BY IF(rank <= 20, rank, 21), name;
Самый внутренний запрос, dummy
, инициализирует нашу @rank
переменную. Следующая производная таблица, dateranked
, ранжирует все строки по дате (разрывая связи на name
). Внешний запрос затем просто переупорядочивает строки по нашим вычисленным rank
, обрабатывая ранги больше 20 как ранг # 21, а затем name
.
ОБНОВЛЕНИЕ: Эта версия запроса более компактна, помещает логику условного ранжирования в крайний ORDER BY, использует IF () вместо CASE / END.