简体   繁体   中英

Converting mysql query to Laravel query builder

I am working with Laravel first time. I have (just for example, to make relations easy to understand) books , authors , author_book and descriptions tables. And I need descriptions table as separate table, don't ask me why.

So, I wrote some mysql query to show you my intentions. It has a subquery to get all authors as a string first.

    SELECT temp.book_id, temp.names, books.title FROM descriptions 
        LEFT JOIN books ON descriptions.book_id = books.id 
        LEFT JOIN (     
            SELECT author_book.book_id, GROUP_CONCAT(authors.name ORDER BY authors.name SEPARATOR ', ') as names FROM author_book 
                LEFT JOIN authors ON author_book.author_id = authors.id 
            GROUP BY author_book.book_id) temp ON temp.book_id = books.id 
    ORDER BY temp.names, books.title

This query retrieves the list of all books, which have description, and orders them by authors and titles. Like here:

  • Alex Banks, Eve Porcello - Learning React: Functional Web Development with React and Redux
  • Charlotte Lucas - Dein perfektes Jahr: Roman
  • Charlotte Lucas - Your Perfect Year: A Novel Kindle Edition Marc
  • Garreau, Will Faurot - Redux in Action

My question is how can I do the same thing using Laravel query builder?

you can make it like this

$subJoin = 
author_book::select('author_book.book_id',DB::raw('GROUP_CONCAT(authors.name ORDER BY 
authors.name SEPARATOR ', ') as names'))
->leftJoin('authors','author_book.author_id','=','authors.id')
->groupBy(author_book.book_id)
->get();

$query = descriptions::leftJoin('books','books.id','=','descriptions.book_id')
                  ->joinSub($subJoin,'temp',function ($join) {
                    $join->on('temp.book_id', '=', 'books.id');

                })->orderBy('temp.names', 'books.title')
                  ->get();

You have used hasOne and hasMany Relationship in the laravel model class.

First, you need to learn how to use the join model in laravel with the primary key to foreign key.

for more information, you need to refer this URL to join query in laravel.

Please check below URL for a join query

https://laravel.com/docs/5.8/eloquent-relationships

Comment from Alex Guerrero was really helpfull. My solution is based on it. Tip from Saly 3301 to use online converter https://pontaku-tools.com/english/ could be usefull, but the tool doesn't work well with complicated queries.

I also found a way to check what sql string query builder generates. It is possible to call ->toSql() method on query builder instance. You should do it before calling ->get() or ->paginate() methods.

    $sql = DB::table('users')->toSql();
    var_dump($sql);

My final solution for Laravel 5.8:

    $joined_authors = DB::table('author_book')
        ->select('author_book.book_id', DB::raw('GROUP_CONCAT(authors.name ORDER BY authors.name SEPARATOR ", ") as names'))
        ->leftJoin('authors', 'author_book.author_id', '=', 'authors.id')
        ->groupBy('author_book.book_id');

    $books_with_description = DB::table('descriptions')
        ->leftJoin('books', 'descriptions.book_id', '=', 'books.id')
        ->leftJoinSub($joined_authors, 'joined_authors', function ($join) {
            $join->on('joined_authors.book_id', '=', 'books.id');
        })
        ->orderBy('joined_authors.names')
        ->orderBy('books.title')
        ->paginate(15);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM