find_in_set with join in laravel

Viewed 1321

How to get the desire output using laravel query. Tried that way does not get success please guide thanks a lot in advance

Is there any way we can set it in model if possible please guide

User

id  name    b_id
1   Alax    1,3
2   Rex     2,4
3   Lex     2,3

Books

id  book_name   book_author
1   Javascript  jim
2   PHP         json
3   LARAVEL     rax
4   SYMPHONY    Alax

Output

id  name    b_id
1   Alax    Javascript, LARAVEL
2   Rex PHP, SYMPHONY
3   Lex PHP, LARAVEL

And Query:

$res = DB::table('user')->leftJoin('book', function($join){
   $join->on(DB::raw("find_in_set(book.id, user.b_id)",DB::raw(''),DB::raw('')));
});
2 Answers

Try this.

$data = \DB::table("user")
        ->select("user.*",\DB::raw("GROUP_CONCAT(book.book_name) as book_name"))
        ->leftjoin("book",\DB::raw("FIND_IN_SET(book.id,user.b_id)"),">",\DB::raw("'0'"))
        ->get();


\DB::raw("GROUP_CONCAT(CONCAT(book.book_name, ' - ', book.book_author) SEPARATOR ', ') AS book_name_author")

Your output looks like.

Illuminate\Support\Collection Object

(

    [items:protected] => Array

        (

            [0] => stdClass Object
                (
                    [id] => 1
                    [name] => Alax
                    [b_id] => 1,3
                    [book_name] => Javascript,LARAVEL
                )

            [1] => stdClass Object
                (
                    [id] => 2
                    [name] => Rex
                    [b_id] => 2,4
                    [book_name] => PHP,SYMPHONY
                )
            [2] => stdClass Object
                (
                    [id] => 3
                    [name] => Lex
                    [b_id] => 2,3
                    [book_name] => PHP,LARAVEL
                )

        )

)

I don't know the exact Laravel syntax problem you are currently facing, but there is a potential problem with your current left join logic. If a given user have more than one matching book, then he would appear in the result set one time for each match. This presumably is not what you want, so I would suggest joining using EXISTS logic:

SELECT u.id, u.name
FROM User u
WHERE EXISTS (SELECT 1 FROM Books b WHERE FIND_IN_SET(b.id, u.b_id) > 0);

The Laravel code:

$res = DB::table('user u')
    ->whereExists(function ($query) {
        $query->select(DB::raw(1))
              ->from('book b')
              ->whereRaw('FIND_IN_SET(b.id, u.b_id) > 0');
        })
    ->get();

The exists approach ensures that each user would only appear once in the result set.

Related