【问题标题】:Fetching model objects with distinct column values获取具有不同列值的模型对象
【发布时间】:2017-07-03 06:46:42
【问题描述】:

我有一个applications 表,其中包含user_idemailphone 等。申请人可能会或可能不会创建用户帐户,因为注册是可选的;因此user_id 可以为空。它们还可能使用同一个电子邮件地址多次应用,在这种情况下,applications 表中的email 将在多个记录中重复。

现在,目标是获取所有 Application 模型实例,不包括重复项。例如:如果 Jack 使用 jack@gmail.com 应用了五次,则 applications 表将有 5 条记录,其中 email 列设置为 jack@gmail.com。在获取Applications 时,我只想获取一条jack@gmail.com 的记录,其他四条应该忽略。

所以,我尝试了多种方法,但它们要么获取了所有记录,要么根本不执行:

  1. groupBy('email') 失败,get() 因为非聚合列 email

    Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'applications.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

    同时,groupBy('email')->get(['email']) 运行良好,但问题是我还需要其他列(至少 created_at),理想情况下 - 完整的 Application 模型实例。

  2. Application::whereIn('id', function($query) { $query->select('id')->groupBy('email'); })->get()返回表中的所有记录

  3. Application::select('*', 'DISTINCT email')->get() 结果

    Column not found: 1054 Unknown column 'DISTINCT email' in 'field list'

    Eloquent 方法 Application::distinct()->get(['email']) 提供了正确的电子邮件列表,但我需要更多的列,而不仅仅是电子邮件。一旦我开始选择更多列,我就会不断获取所有记录作为结果。

  4. 由于启用了严格模式,以下所有查询均失败:

    • SELECT * FROM ( SELECT * FROM applications ORDER BY id DESC ) AS tmp GROUP BY email
    • SELECT * FROM applications WHERE id IN(SELECT id FROM applications GROUP BY email)
    • SELECT email, id, created_at from ( SELECT email, id, created_at FROM applications) apps group by email

谁能帮我找出正确的方法?如果 Eloquent 可以解决我的问题/限制,我很乐意使用 Eloquent 并使用实际模型,而不是 stdObj 或其他。

附:我使用的 SQL 引擎是启用严格模式的 MySQL

【问题讨论】:

    标签: laravel eloquent laravel-5.4


    【解决方案1】:

    首先,如果你想在你的 eloquent 中加入一个表达式,你必须使用DB::raw('DISTINCT email')

    其次,我认为你应该采用这种方法:

    Application::select('id', 'email', 'more_fields')->groupBy('email')->get();
    

    您的select() 函数中必须有您按它分组的列。

    最后一个选项:

    您可以在 eloquent 查询中使用 ->distinct() 函数来删除重复项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多