возможно, это не тот запрос, который вы запрашиваете, но это чистый и простой запрос, который я использовал в вашей ситуации:
select objects.*, matrix.*
from
(select users.id, o.key
from users, (select distinct key from objects) as o
)
as matrix left join objects on matrix.id = objects.user_id
and matrix.key = objets.key
order by matrix.id, matrix.key
Этот запрос «заполняет» пустые места. Таким образом, вы можете использовать набор результатов с двумя вложенными foreach (или чем-то подобным) и нарисовать нужную таблицу.