Thank you, but I did LEFT JOIN, so any records in tasks where assigneeId is null should still be selected.
I managed to figure out the problem. It was that I didn’t SELECT DISTINCT when producing the derived table, which means if multiple tasks were assigned to the same employee, the derived table would have identical rows, and, when joined with table tasks, those tasks with the same assigneeId would be joined with duplicate rows.
Or, I could have gone with an even simpler solution:
SELECT t.taskId, e1.name, e2.name
FROM tasks t
JOIN employees e1 ON t.authorId = e1.id
LEFT JOIN employees e2 ON t.assigneeId = e2.id;