在Laravel Eloquent模型中添加一个计算列,并在该列上进行排序和/或过滤。

huangapple go评论85阅读模式
英文:

Add a calculated column to a Laravel Eloquent model and sort and/or filter on that column

问题

我正在尝试在Laravel/Eloquent中编写一个包含计算列的查询,查询的结果集需要基于计算列进行排序和/或筛选。查询如下:

SELECT member_names.id,
       member_names.member_id,
       member_names.membership_owner,
       Concat(member_names.last_name, " ", suffixes.description, ", ", surnames.description, " ", member_names.first_name, " ") as name,
       vip_codes.description,
       membership_types.description,
       membership_statuses.description
FROM member_names
     LEFT JOIN members ON member_names.member_id = members.id
     LEFT JOIN surnames ON member_names.surname_id = surnames.id
     LEFT JOIN suffixes ON member_names.suffix_id = suffixes.id
     LEFT JOIN vip_codes ON member_names.vip_code_id = vip_codes.id
     LEFT JOIN membership_types ON members.membership_type_id = membership_types.id
     LEFT JOIN membership_statuses ON members.membership_status_id = membership_statuses.id
WHERE member_names.membership_owner=1
ORDER BY name;

计算列是 name,使用以下方式计算:

Concat(member_names.last_name, " ", suffixes.description, ", ", surnames.description, " ", member_names.first_name, " ") as name

这个查询独特之处在于它需要访问 suffixes 和 surnames 表来计算列,而不仅仅在同一表中操作。

你提到你有 member_names、members、surnames、suffixes、vip_codes、membership_types 和 membership_statuses 的模型,并且它们都已正确连接。换句话说,你可以发出简单的查询,如下所示:

MemberName::orderBy('last_name', 'asc')->orderBy('first_name', 'asc')->where('membership_owner', 1)->paginate(10)

在控制器或视图中解决额外的表查找也没有问题。你的问题是你需要在查询中获取组成名称的数据。

你的替代方法是将其转化为数据库中的视图,但我更倾向于不在数据库中添加额外的视图。

感谢Marcin Nabiałek的建议,它起作用得很好。最终的查询版本如下:

$name = 'Concat(member_names.last_name, " ", suffixes.description, ", ", surnames.description, " ", member_names.first_name, " ")';

$memberNames = MemberName::selectRaw("member_names.*, {$name} as name")
    ->leftJoin('members', 'member_names.member_id', '=', 'members.id')
    ->leftJoin('surnames', 'member_names.surname_id', '=', 'surnames.id')
    ->leftJoin('suffixes', 'member_names.suffix_id', '=', 'suffixes.id')
    ->orderByRaw($name)
    ->paginate(10);

对于 vip_codes、membership_types 和 membership_statuses 的左连接在视图中进一步下游才需要,因此在这一点上可以省略,Eloquent会按照它应该的方式解决它。

有关更多信息,请参阅 Laravel 手册:https://laravel.com/docs/5.8/queries

英文:

I'm trying to code a query in Laravel/Eloquent that contains a calculated column. The result set of that query needs to be sorted and/or filtered based on the calculated column. The query is;

  SELECT member_names.id,
         member_names.member_id,
         member_names.membership_owner,
         Concat(member_names.last_name, " ", suffixes.description, ", ", surnames.description, " ", member_names.first_name, " ") as name,
         vip_codes.description,
         membership_types.description,
         membership_statuses.description
    FROM member_names
         LEFT JOIN members ON member_names.member_id = members.id
         LEFT JOIN surnames ON member_names.surname_id = surnames.id
         LEFT JOIN suffixes ON member_names.suffix_id = suffixes.id
         LEFT JOIN vip_codes ON member_names.vip_code_id = vip_codes.id
         LEFT JOIN membership_types ON members.membership_type_id = membership_types.id
         LEFT JOIN membership_statuses ON members.membership_status_id = membership_statuses.id
   WHERE member_names.membership_owner=1
ORDER BY name;

The calculated column is name and is calculated with the following;

Concat(member_names.last_name, " ", suffixes.description, ", ", surnames.description, " ", member_names.first_name, " ") as name

I believe this one is unique as it needs to reach out to the suffixes and surnames tables to calculate the column. The other answers I've seen so far stay within the table.

I have models for member_names, members, surnames, suffixes, vip_codes, membership_types and membership_statuses. They are all connected properly. In other words, I can issue a simple query with

MemberName::->orderBy('last_name', 'asc')->orderBy(first_name, 'asc')->where('membership_owner', 1)->paginate(10)

and down stream resolve additional table look ups in the controller or view with no problem. My problem is I need the data that comprises the name upstream in the query.

My alternative is to turn this into a view in the database but I'd rather not clutter up the database.

Thank you to Marcin Nabiałek for the advise. Worked like a charm. The final version of the query, for us newbies, is as follows;

$name = 'Concat(member_names.last_name, " ", suffixes.description, ", ", surnames.description, " ", member_names.first_name, " ")';

$memberNames = MemberName::selectRaw("member_names.*, {$name} as name")
    ->leftJoin('members', 'member_names.member_id', '=', 'members.id')
    ->leftJoin('surnames', 'member_names.surname_id', '=', 'surnames.id')
    ->leftJoin('suffixes', 'member_names.suffix_id', '=', 'suffixes.id')
    ->orderByRaw($name)
    ->paginate(10);

The LEFT JOINs for vip_codes, membership_types, and membership_statuses weren't needed until further downstream in the view so they could be left out at this point with Eloquent resolving it as it's supposed to.

For more information see the Laravel manual at: https://laravel.com/docs/5.8/queries

答案1

得分: 2

如果您已经将查询编写为Eloquent,并且需要添加这个单独的列,您可以像这样操作:

$name = 'Concat(member_names.last_name, " ", suffixes.description, ", ", surnames.description, " ", member_names.first_name, " ")';

MemberName::selectRaw("member_names.*, {$name} as name") 
   // 在这里添加您需要的连接和其他代码
   ->orderByRaw($name)
   ->paginate(10)
英文:

If you have already they query written as Eloquent and you need to add this single column, you can do something like this:

$name = 'Concat(member_names.last_name, " ", suffixes.description, ", ", surnames.description, " ", member_names.first_name, " ")';

MemberName::selectRaw("member_names.*, {$name} as name") 
   // here you put joins and other code you need
->orderByRaw($name)
->paginate(10)

huangapple
  • 本文由 发表于 2020年1月4日 01:27:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/59582814.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定