Optimizing Laravel Eloquent multiple joins
SQL formatting

Your SQL script in my opinion could use some indentation and a few more line breaks. 

Variable names

Table &amp; column aliases are useful. But it is a good practice to use a variable name that at least says something about what the table contains. 

Consistency

SQL is not case sensitive, but still it is good practice to use one style and stick to it. 

Here is the same script that reads much more easily

SELECT 
    Bk.title, 
    GROUP_CONCAT
        (
        DISTINCT (Gnr.name) ORDER BY Gnr.relevancy, 
        Gnr.name ASC 
        SEPARATOR ' '
        ) AS genre_list, 
    GROUP_CONCAT
        (
        DISTINCT CAST(Gnr.relevancy AS CHAR) ORDER BY Gnr.relevancy ASC 
        SEPARATOR ','
        ) AS genre_relevancy, 
    BkGnr.book_id 
FROM book_genres BkGnr 
    INNER JOIN genre_book Gnr 
        ON BkGnr.genre_id = Gnr.id 
        AND Gnr.id IN (". (($genreIdList) ? $genreIdList : 0) . ") 
    INNER JOIN book Bk 
        ON BkGnr.book_id = Bk.id
    INNER JOIN licensors Lic 
        ON Bk.licensor_id = Lic.id 
WHERE Bk.status = 'active' 
    AND Bk.premium = 'yes' 
    AND Lic.status = 'active' 
GROUP BY BkGnr.book_id


SQL functions

This doesn't seem to make sense:

DISTINCT (Gnr.name)

DISTINCT CAST(Gnr.relevancy AS CHAR)


Why would there be duplicate genre name records... wouldn't that defeat the purpose of normalizing into a Genre type of table? 

Also I don't think casting as CHAR is a good idea. Use VARCHAR instead. If you know about what the maximum character lenght should be, specify it so RDBMS doesn't have to guess, e.g., VARCHAR(50). 

This is a bad idea.

AND Gnr.id IN (". (($genreIdList) ? $genreIdList : 0) . ") 


It is bad practice to concatenate PHP and SQL together. Instead, use prepared statements with PDO. 

SQL procedure


  This is the PHP/Eloquent version:


This whole section looks messy. You would gain clarity, repeatability and performance by using a SQL stored procedure. I'm going to assume your RDBMS is MySQL as is most common with PHP. Here is what you would execute once in MySQL to create it:

DROP PROCEDURE sp_genreIdList IF EXISTS;
DELIMITER | 
CREATE PROCEDURE sp_genreIdList (IN p_genreIdList VARCHAR) -- assuming you are passing a string type parameter to RDBMS
AS
BEGIN
SELECT 
    Bk.title, 
    GROUP_CONCAT
        (
        DISTINCT (Gnr.name) ORDER BY Gnr.relevancy, 
        Gnr.name ASC 
        SEPARATOR ' '
        ) AS genre_list, 
    GROUP_CONCAT
        (
        DISTINCT CAST(Gnr.relevancy AS CHAR) ORDER BY Gnr.relevancy ASC 
        SEPARATOR ','
        ) AS genre_relevancy, 
    BkGnr.book_id 
FROM book_genres BkGnr 
    INNER JOIN genre_book Gnr 
        ON BkGnr.genre_id = Gnr.id 
        AND Gnr.id IN (". (($genreIdList) ? $genreIdList : 0) . ") 
    INNER JOIN book Bk 
        ON BkGnr.book_id = Bk.id
    INNER JOIN licensors Lic 
        ON Bk.licensor_id = Lic.id 
WHERE Bk.status = 'active' 
    AND Bk.premium = 'yes' 
    AND Lic.status = 'active' 
GROUP BY BkGnr.book_id;
END|
DELIMITER ; --make sure you don't forget that line


Then from PHP you simply:

$sql = "CALL sp_genreIdList("$genreIdList");";


Or something similar. And you can do this from multiple scripts in multiple languages and you will still get consistent results from RDBMS.