Можно использовать row_number()
и условное агрегирование:
select bookId,
max(case when seqnum = 1 then genre end) as genre_1,
max(case when seqnum = 2 then genre end) as genre_2,
max(case when seqnum = 3 then genre end) as genre_3
from (select bg.*,
row_number() over (partition by bookId order by genre) as seqnum
from bookGenres
) bg
group by bookId;