Puoi sostituire i valori con qualcosa del genere:
select
case when rownum = 1 then title else null end title,
name,
category_id
from
(
SELECT c.title,
i.name,
i.category_id,
@row:=(case when @prev=title and @precat=category_id
then @row else 0 end) + 1 as rownum,
@prev:=title ptitle,
@precat:=category_id pcat
FROM items AS i
INNER JOIN categories AS c
ON c.id = i.category_id
order by i.category_id, c.title
) src
order by category_id, rownum
Vedi SQL Fiddle con demo
Il risultato è:
| TITLE | NAME | CATEGORY_ID |
---------------------------------
| red | apple | 1 |
| (null) | car | 1 |
| (null) | paper | 1 |
| yellow | lego | 2 |
| (null) | banana | 2 |
| blue | pen | 3 |