如何在Laravel中获取非键列字段的不同值?

gth*_*huo 66 builder laravel eloquent

这可能很容易,但不知道如何.

我有一个表可以具有特定非键列字段的重复值.如何使用查询生成器或Eloquent编写SQL查询,该查询将获取具有该列的不同值的行?

请注意,我不是仅提取该列,而是与其他列值一起提取,因此distinct()可能无法正常工作.所以这个问题基本上可以是如何指定我想在查询中区分的列,现在不distinct()接受任何参数?

Mar*_*łek 91

你应该用groupby.在Query Builder中,您可以这样做:

$users = DB::table('users')
            ->select('id','name', 'email')
            ->groupBy('name')
            ->get();
Run Code Online (Sandbox Code Playgroud)

  • 如果你不想应用任何数学运算,如SUM,AVG,MAX等"group by"不是正确的答案(你可以使用它,但你不应该使用它).你应该使用distinct.在MySQL中,您可以使用DISTINCT作为列并向结果集添加更多列:"SELECT DISTINCT name,id,email FROM users".有了雄辩,你可以用$ this-> select(['name','id','email']) - > distinct() - > get(); (8认同)
  • 我有一个表“消息”(用于聊天),我想获取经过身份验证的用户从每个对话中收到的最新消息。使用 groupBy 我只能得到一条消息,但我得到第一条消息,我需要最后一条消息。似乎 orderBy 不起作用。 (2认同)
  • 当我添加一个 `where()` 时它会中断,我该如何解决这个问题? (2认同)
  • 需要注意的是:“group by”与“distinct”不同。“group by”将改变 SQL 查询中聚合函数(例如“count()”)的行为。`distinct` 不会改变此类函数的行为,因此根据您使用的函数,您会得到不同的结果。 (2认同)

Pat*_*ros 55

在Eloquent中你也可以像这样查询:

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

  • 问题特别问:"请注意,我不是仅提取该列,而是与其他列值一起提供" (10认同)
  • @Hirnhamster:Okkei.但是,这个答案对于路过的其他人来说仍然有用...... (9认同)
  • 对我来说没有用,我专门查看OP是什么。这不是一个容易的发现。 (3认同)
  • `$users = User::select('column1', 'column2', 'column3')->distinct()->get();` (2认同)
  • 这应该是国际海事组织接受的答案 (2认同)

Sal*_*lar 22

在雄辩中你可以使用它

$users = User::select('name')->groupBy('name')->get()->toArray() ;
Run Code Online (Sandbox Code Playgroud)

groupBy实际上是获取不同的值,实际上groupBy会对相同的值进行分类,以便我们可以对它们使用聚合函数.但在这种情况下,我们没有聚合函数,我们只是选择将导致结果具有不同值的值

  • 这是如何运作的?groupBy实际上是在获取不同的用户名吗?你能不能再解释一下这是如何解决问题的呢? (4认同)
  • 结果是一样的,这取决于你的项目是使用 ORM 还是使用查询生成器,如果你使用其中之一,那么最好坚持使用那个。这就是为什么我以不同的方式回答你的问题。 (2认同)

Jed*_*nch 15

如果数据库规则不允许任何选择字段位于聚合函数之外,则分组依据将不起作用。而是使用laravel 集合

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

foreach($users->unique('name') as $user){
  //....
}
Run Code Online (Sandbox Code Playgroud)

有人指出,这对于大型集合的性能可能不是很好。我建议在集合中添加一个键。要使用的方法称为keyBy。这是简单的方法。

     $users = DB::table('users')
        ->select('id','name', 'email')
        ->get()
        ->keyBy('name');
Run Code Online (Sandbox Code Playgroud)

keyBy 还允许您为更复杂的事情添加回调函数......

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

如果您必须迭代大型集合,向它添加一个键可以解决性能问题。


rsa*_*ale 14

虽然我迟到了回答这个问题,但使用Eloquent获取不同记录的更好方法是

$user_names = User::distinct()->get(['name']);
Run Code Online (Sandbox Code Playgroud)


Rob*_*lia 12

**

已针对 Laravel 5.8 进行测试

**

由于您想从表中获取所有列,您可以收集所有数据,然后使用名为Unique 的Collections 函数对其进行过滤

// Get all users with unique name
User::all()->unique('name')
Run Code Online (Sandbox Code Playgroud)

或者

// Get all & latest users with unique name 
User::latest()->get()->unique('name')
Run Code Online (Sandbox Code Playgroud)

有关更多信息,您可以查看Laravel 集合文档

编辑:您可能会遇到性能问题,通过使用 Unique(),您将首先从 User 表中获取所有数据,然后 Laravel 将对其进行过滤。如果您有大量用户数据,这种方式并不好。您可以使用查询构建器并调用您想要使用的每个字段,例如:

User::select('username','email','name')->distinct('name')->get();
Run Code Online (Sandbox Code Playgroud)


Lat*_*san 7

我发现这种方法(对我来说)工作得很好,可以生成唯一值的平面数组:

$uniqueNames = User::select('name')->distinct()->pluck('name')->toArray();
Run Code Online (Sandbox Code Playgroud)

如果您运行->toSql()此查询生成器,您将看到它生成如下查询:

select distinct `name` from `users`
Run Code Online (Sandbox Code Playgroud)

由照亮\集合库处理->pluck()(不通过 sql 查询)。


jec*_*006 5

请注意,groupBy上面使用的方法不适用于postgres。

使用distinct可能是一个更好的选择-例如 $users = User::query()->distinct()->get();

如果使用query,则可以根据要求选择所有列。


Mar*_*ero 5

$users = User::select('column1', 'column2', 'column3')->distinct()->get();检索表中不同行的所有三个库姆。您可以根据需要添加任意数量的列。