¿Estás buscando esto?
SELECT rn, id, category_id, title
FROM
(
SELECT *, @a := IF(@c = category_id, @a + 1, 1) rn, @c := category_id
FROM photos CROSS JOIN (SELECT @c := NULL, @a := 0) i
ORDER BY category_id
) q
WHERE rn <= 4;
Salida:
| RN | ID | CATEGORY_ID | TITLE | |----|----|-------------|--------| | 1 | 43 | 1 | Title1 | | 1 | 28 | 2 | Title2 | | 2 | 42 | 2 | Title3 | | 1 | 11 | 3 | Title4 | | 1 | 3 | 4 | Title5 | | 2 | 29 | 4 | Title6 | | 3 | 33 | 4 | Title7 |
Aquí está SQLFiddle demostración
Aquí hay una solución para que su código produzca los números de fila correctos
SET @a:=0;
SET @cid:=0;
SELECT @a, @cid, q.*, @cid:=q.category_id FROM (
SELECT *
FROM photos
ORDER BY category_id
) AS q
WHERE @a := IF(@cid=q.category_id, @a+1, 1)
Aquí está SQLFiddle demostración
El orden de ejecución de las instrucciones SQL sí importa.