How to get distinct values for non-key column fields in Laravel?

前端 未结 14 1391
太阳男子
太阳男子 2020-12-01 09:09

This might be quite easy but have no idea how to.

I have a table that can have repeated values for a particular non-key column field. How do I write a SQL query usin

相关标签:
14条回答
  • 2020-12-01 09:22

    I had the same issues when trying to populate a list of all the unique threads a user had with other users. This did the trick for me

    Message::where('from_user', $user->id)
            ->select(['from_user', 'to_user'])
            ->selectRaw('MAX(created_at) AS last_date')
            ->groupBy(['from_user', 'to_user'])
            ->orderBy('last_date', 'DESC')
            ->get()
    
    0 讨论(0)
  • 2020-12-01 09:25

    Though I am late to answer this, a better approach to get distinct records using Eloquent would be

    $user_names = User::distinct()->get(['name']);
    
    0 讨论(0)
  • 2020-12-01 09:26

    **

    Tested for Laravel 5.8

    **

    Since you wanna get all columns from the table, you can collect all of the data and then filter it using Collections function called Unique

    // Get all users with unique name
    User::all()->unique('name')
    

    or

    // Get all & latest users with unique name 
    User::latest()->get()->unique('name')
    

    For more information you can check Laravel Collection Documentations

    EDIT: You might have issue with perfomance, by using Unique() you'll get all data first from User table, and then Laravel will filter it. This way isn't good if you have lots of Users data. You can use query builder and call each fields that you wanna use, example:

    User::select('username','email','name')->distinct('name')->get();
    
    0 讨论(0)
  • 2020-12-01 09:26

    For those who like me doing same mistake. Here is the elaborated answer Tested in Laravel 5.7

    A. Records in DB

    UserFile::orderBy('created_at','desc')->get()->toArray();

    Array
    (
        [0] => Array
            (
                [id] => 2073
                [type] => 'DL'
                [url] => 'https://i.picsum.photos/12/884/200/300.jpg'
                [created_at] => 2020-08-05 17:16:48
                [updated_at] => 2020-08-06 18:08:38
            )
    
        [1] => Array
            (
                [id] => 2074
                [type] => 'PROFILE'
                [url] => 'https://i.picsum.photos/13/884/200/300.jpg'
                [created_at] => 2020-08-05 17:20:06
                [updated_at] => 2020-08-06 18:08:38
            )
    
        [2] => Array
            (
                [id] => 2076
                [type] => 'PROFILE'
                [url] => 'https://i.picsum.photos/13/884/200/300.jpg'
                [created_at] => 2020-08-05 17:22:01
                [updated_at] => 2020-08-06 18:08:38
            )
    
        [3] => Array
            (
                [id] => 2086
                [type] => 'PROFILE'
                [url] => 'https://i.picsum.photos/13/884/200/300.jpg'
                [created_at] => 2020-08-05 19:22:41
                [updated_at] => 2020-08-06 18:08:38
            )
    )
    

    B. Desired Grouped result

    UserFile::select('type','url','updated_at)->distinct('type')->get()->toArray();

    Array
    (
        [0] => Array
            (
                [type] => 'DL'
                [url] => 'https://i.picsum.photos/12/884/200/300.jpg'
                [updated_at] => 2020-08-06 18:08:38 
            )
    
        [1] => Array
            (
                [type] => 'PROFILE'
                [url] => 'https://i.picsum.photos/13/884/200/300.jpg'
                [updated_at] => 2020-08-06 18:08:38
            )
    )
    

    So Pass only those columns in "select()", values of which are same. For example: 'type','url'. You can add more columns provided they have same value like 'updated_at'.

    If you try to pass "created_at" or "id" in "select()", then you will get the records same as A. Because they are different for each row in DB.

    0 讨论(0)
  • 2020-12-01 09:32

    In Eloquent you can also query like this:

    $users = User::select('name')->distinct()->get();

    0 讨论(0)
  • 2020-12-01 09:32

    Grouping by will not work if the database rules don't allow any of the select fields to be outside of an aggregate function. Instead use the laravel collections.

    $users = DB::table('users')
            ->select('id','name', 'email')
            ->get();
    
    foreach($users->unique('name') as $user){
      //....
    }
    

    Someone pointed out that this may not be great on performance for large collections. I would recommend adding a key to the collection. The method to use is called keyBy. This is the simple method.

         $users = DB::table('users')
            ->select('id','name', 'email')
            ->get()
            ->keyBy('name');
    

    The keyBy also allows you to add a call back function for more complex things...

         $users = DB::table('users')
            ->select('id','name', 'email')
            ->get()
            ->keyBy(function($user){
                  return $user->name . '-' . $user->id;
             });
    

    If you have to iterate over large collections, adding a key to it solve the performance issue.

    0 讨论(0)
提交回复
热议问题