ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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


M
Marcin Nabiałek

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

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

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

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

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

问题特别问Note that I am not fetching that column only, it is in conjunction with other column values
@Hirnhamster:Okkei。但是,这个答案对于路过的其他人仍然有用......
对我没用,我专门看 OP 是什么。它不是一个容易的发现。
$users = User::select('column1', 'column2', 'column3')->distinct()->get();
这应该是我接受的答案
S
Salar

雄辩地你可以使用这个

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

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


这是如何运作的? groupBy 实际上是在获取不同的用户名吗?您能否再解释一下这如何回答 op 的问题?
是的 groupBy 实际上是获取不同的值,实际上 groupBy 将对相同的值进行分类,以便我们可以对它们使用聚合函数。但在这种情况下,我们没有聚合函数,我们只是选择会导致结果具有不同值的值。
我明白了.. 那么,这个答案与 Marcin 的答案有何不同?有不同的答案是可以的,只要你能解释它有什么不同以及它解决了什么缺陷:) 不要费心在评论中回答,请直接用相关信息编辑你的问题。
结果是一样的,这取决于您的项目是使用 ORM 还是使用查询生成器,如果您使用其中之一,那么最好坚持使用那个。这就是为什么我以不同的方式回答你的问题。
好吧,我有这个问题,如果您现在想使用 in_array() 函数检查项目是否存在,它永远不会工作。为了解决这个问题,我尝试了 ->lists()(版本 5.2)。因此,$users = User::select('name')->groupBy('name')->lists('name'); 对 php 的 in_array() 工作正常;
r
rsakhale

虽然我迟到了,但使用 Eloquent 获得不同记录的更好方法是

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

好的,您通过向我们展示了也可以将字段名称的参数传递给 get() 方法(我也测试过 first() 方法)来增加价值,这相当于使用 select() 方法如这里的一些答案所示。尽管不知何故 groupBy 似乎仍然得分最高。但是,如果这是我选择的唯一列,这将是真正不同的。
性能方面,distinct 将超过 groupBy,因为记录将首先在 SQL 引擎中被选择,这与 Group By 引擎不同,引擎首先选择所有记录,然后再分组。
$user_names = User::distinct()->count(['name']); 也有效
R
Robby Alvian Jaya Mulia

**

经过 Laravel 5.8 测试

**

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

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

或者

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

如需更多信息,您可以查看Laravel Collection Documentations

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

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

这效率不高,因为您首先从 db 获取所有数据
这就是为什么它被称为过滤,您可以使用 distinct() 作为查询构建器,但您无法获取其他字段(无论如何您仍然可以通过 select 调用每个字段)。通过使用 unique() 是获取所有字段而不调用每个字段的唯一方法(尽管我们知道这可能与性能有问题)。
人们在不知道他们实际在做什么的情况下使用此解决方案,令人惊讶!!!
J
Jed Lynch

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

$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;
         });

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


你是对的,这正是我面临的问题......但是等到执行查询并执行集合中的操作也不理想。特别是如果您依赖分页,您的操作将在分页计算之后,并且每页的项目将是错误的。此外,数据库更适合对大数据块进行操作,而不是在代码中检索和处理它。对于小数据块,这将不是问题
你有一个很好的观点。这种方法在大型集合上的性能可能不是很好,而且这不适用于分页。我认为有比我所拥有的更好的答案。
j
jec006

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

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

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


M
Mark-Hero

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


L
Latheesan

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

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

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

select distinct `name` from `users`

->pluck() 由Illumination\collection lib 处理(不是通过sql 查询)。


A
Alex Christodoulou

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

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

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

A
Abms

以下是我测试过的 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();

S
Santosh Kumar

对于那些像我一样犯同样错误的人。这是在 Laravel 5.7 中测试的详细答案

A. 数据库中的记录

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. 期望的分组结果

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

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

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


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅