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

这可能很容易,但不知道如何去做。

我有一个表,它可以为特定的非键列字段重复值。如何使用 QueryBuilder 或 Eloquent 编写 SQL 查询,以便为该列提取具有不同值的行?

请注意,我并不只是获取该列,它与其他列值一起使用,因此 distinct()可能不会真正起作用。所以这个问题基本上可以是如何在 distinct()不接受参数的情况下指定我想在查询中区分的列?

318226 次浏览

你应该使用 groupby。在查询生成器中你可以这样做:

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

你可以用这个

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

GroupBy 实际上是获取不同的值,实际上 groupBy 将对相同的值进行分类,因此我们可以对它们使用聚合函数。但是在这个场景中,我们没有聚合函数,我们只是选择了一个值,这个值会导致结果具有不同的值

在雄辩中你也可以这样查询:

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

注意,上面使用的 groupBy对 postgres 不起作用。

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

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

虽然我回答这个问题已经晚了,但使用雄辩来获得不同记录的更好方法是

$user_names = User::distinct()->get(['name']);

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

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


foreach($users->unique('name') as $user){
//....
}

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

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

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

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

如果必须遍历大型集合,则向其添加一个键可以解决性能问题。

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

我发现这种方法(对我来说)非常有效,可以生成一个由唯一值组成的平面数组:

$uniqueNames = User::select('name')->distinct()->pluck('name')->toArray();

如果在这个查询构建器上运行 ->toSql(),您将看到它生成如下查询:

select distinct `name` from `users`

->pluck()由照明集合库(而不是通过 sql 查询)处理。

**

对 Laravel 5.8进行测试

**

因为您希望从表中获取所有列,所以可以收集所有数据,然后使用称为 独一无二的 Collectionsfunction 对其进行过滤

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

或者

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

更多信息,您可以检查 Laravel 收集文件

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

User::select('username','email','name')->distinct('name')->get();

在尝试填充用户与其他用户之间所有唯一线程的列表时,我遇到了同样的问题。这招对我很管用

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()

对于那些喜欢我做同样的错误。这里是详细的答案 在 Laravel 5.7中测试

数据库中的记录

UserFile: : orderBy (‘ create _ 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
)
)

期望的分组结果

UserFile: : select (‘ type’,‘ url’,‘ update _ at)-> different (‘ 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
)
)

所以只传递 "select()"中值相同的那些列。 例如: 'type','url'。您可以添加更多的列,只要它们具有与 'updated_at'相同的值。

如果您尝试在 "select()"中传递 "created_at""id",那么您将获得与 A 相同的记录。 因为它们对于 DB 中的每一行都是不同的。

// Get unique value for table 'add_new_videos' column name 'project_id'
$project_id = DB::table('add_new_videos')->distinct()->get(['project_id']);

下面是我测试过的3种方法,它们都能得到相同的结果:

User::distinct()->get(['name'])->pluck('name');


User::select('name')->distinct()->pluck('name')->all();


DB::table('users')->select('name')->groupBy('name')->get()->pluck('name')->all();

在我的情况下(与 Laravel 9号) ,我需要:-

  1. 使用 哪里条款
  2. 得到 完整的一行
  3. 得到特定列的 独一无二的条目

作为比较复杂的查询,不过我还是有一个简单的方法。也许对你也有帮助。

User::where('id',auth()->user()->id)->distinct('name')->get();