Select joined table with same column name but different value using eloquent - laravel

I'm trying to call 2 columns from 2 different tables. applicants.ic_no and agents.ic_no. It have different values.
Using the following codes only displayed only ic_no from agents.ic_no
$claimLists = ClaimDetail::join('applicants', 'applicants.ic_no', '=', 'claim_details.ic_no')
->join('agents', 'agents.id', '=', 'claim_details.agent_id')
->where('claim_date', $cutt_off)
->groupBy('agents.id', 'claim_details.id', 'applicants.id')
->orderBy('agents.id')
->orderby('amount', 'desc')
->get();
How do i get both columns to display?

This is because, you have ic_no in both tables. By default MYSQL picks one of it to display, it is the same as having id in both tables and from your results, how would you know which table's ic_no you are accessing while they have the same name?
Alternatively you can use select and DB::raw to change the name of one of the ic_no fields, and similiarly for any other similiar fields. For example;
$claimLists = ClaimDetail::join('applicants', 'applicants.ic_no', '=', 'claim_details.ic_no')
->join('agents', 'agents.id', '=', 'claim_details.agent_id')
->select('claim_details.*', DB::raw('agents.ic_no as agents_ic_no'), 'agents.XXX', 'agents.YYYY', 'applicants.XXX')
->where('claim_date', $cutt_off)
->groupBy('agents.id', 'claim_details.id', 'applicants.id')
->orderBy('agents.id')
->orderby('amount', 'desc')
->get();
instead of XXX and YYY, you can put the fields that you would like to get and you can get as many as you want or remove them, if you don't want to get any field from the second table, but the main thing here is you are access the agents.ic_no as agents_ic_no or whatever name you would like to give it.

I solve this issue by adding select to rename the conflict column name. So this is the code:
$processed = ClaimDetail::join('applicants', 'applicants.ic_no', '=', 'claim_details.ic_no')
->join('agents', 'agents.id', '=', 'claim_details.agent_id')
->select('*')
->selectRaw('applicants.ic_no as nokp, agents.ic_no as agic')
->where('claim_details.agent_id',$agent->id)
->orderBy('claim_details.claimable', 'desc')
->orderby('claim_details.amount', 'desc')
->get();
Thanks guys for your time.

Related

I get the same row duplicated as the result when I do a simple join using the laravel's DB facade

Code
$result = DB::table('disaster_rescue_data')
->join('users', 'disaster_rescue_data.username', '=', 'users.email')
->get();
Problem
I have this very simple join as mentioned in the above code. However when I render the data on a view or dd the $result, I get the same row duplicated and I can not figure out why. (The rows contain the same data.)
(I am using Laravel 5.4)
Can someone please help me figure out why? (I tried different techniques and none of them worked! Thanks.)
to prevent duplication, you should use distinct() method, this method Returns only unique items from the result.
in order to do that, first you must stricly select what you want:
$result = DB::table('disaster_rescue_data')
->select('disaster_rescue_data.*')
->join('users', 'disaster_rescue_data.username', '=', 'users.email')
->distinct()->get();
You could try using distinct in the query. Distinct removes duplicates in a result set.
For example
$result = DB::table('disaster_rescue_data')
->distinct()
->join('users', 'disaster_rescue_data.username', '=', 'users.email')
->get();
See https://laravel.com/docs/5.4/queries
EDIT:
Ok, I am thinking you can now use groupBy to get the unique results. Although it's not clear what your data structure is so this is a guess to use "users.email". Maybe it could be "disaster_rescue_data.username" to group by. Experiment and see.
$result = DB::table('disaster_rescue_data')
->distinct()
->join('users', 'disaster_rescue_data.username', '=', 'users.email')
->groupBy('users.email')
->get();

How to count two related tables using Laravel Query Builder?

I have two tables in my database
My first table
And my second table
I would like to count how many gold members exists and how many silver members exists... I want to do a single count for each category... The rif can be repeated in the column but is the key to join the two tables.. I'm working with Query Builder and I would like to continue work with that. Someone can help me?
I tried with this code but didn't work
$count = DB::table('table1')
->join('table2', 'table1.rif', '=', 'table2.rif')
->select(DB::raw('category')
->count();
Try this:
use Illuminate\Support\Facades\DB;
DB::table('table2')
->join('table1', 'table2.rif', '=', 'table1.rif')
->select(DB::raw('count(*) as count'), 'table1.category as category')
->groupBy('category')
->get();
If you want to count only a specific category:
DB::table('table2')
->join('table1', 'table2.rif', '=', 'table1.rif')
->where('table1.category', 'Silver')
->count()
See Laravel docs for more info.

Pagination creates an error

Im trying to paginate a search to bring back pages of 18 items. Previously i had this code working code:
$productsQuery = Product::where('approved', '=', 1)->leftJoin('reviews', 'reviews.products_id', '=', 'products.id')->select('products.*', DB::raw('AVG(ratings) as ratings_average' ))->groupBy('id')->orderBy('ratings_average', 'DESC');
I add on paginate to this as shown in the docs
$productsQuery = Product::where('approved', '=', 1)->leftJoin('reviews', 'reviews.products_id', '=', 'products.id')->select('products.*', DB::raw('AVG(ratings) as ratings_average' ))->groupBy('id')->orderBy('ratings_average', 'DESC')->paginate(18);
And get an error
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in group statement is ambiguous
Any ideas on how to paginate the statement?
It's not neccesarily the pagination which is causing the issue, the error is caused by your group by.
You should place the table name / alias name prior to the id EG:
$productsQuery = Product::where('approved', '=', 1)->leftJoin('reviews', 'reviews.products_id', '=', 'products.id')->select('products.*', DB::raw('AVG(ratings) as ratings_average' ))->groupBy('product.id OR reviews.id')->orderBy('ratings_average', 'DESC');
Please see the ammended statement above, note that copy pasting it won't work, you'll see to change that groupby argument.
You should also visit the docs on Eloquent, you have approached this in a way where you're fighting laravel. I would suggest getting a tighter grip on the ORM used.
Good luck!
The error is pretty self explanatory here:
Column 'id' in group statement is ambiguous
so you need to make
`groupBy('id')`
more explicit, by telling which id (from which table, as each table used in your query features id column) you want to be used for grouping.

Order by relationship column

I have the following query:
$items = UserItems::with('item')
->where('user_id','=',$this->id)
->where('quantity','>',0)
->get();
I need to order it by item.type so I tried:
$items = UserItems::with('item')
->where('user_id','=',$this->id)
->where('quantity','>',0)
->orderBy('item.type')
->get();
but I get Unknown column 'item.type' in 'order clause'
What I am missing?
join() worked fine thanks to #rypskar comment
$items = UserItems
::where('user_id','=',$this->id)
->where('quantity','>',0)
->join('items', 'items.id', '=', 'user_items.item_id')
->orderBy('items.type')
->select('user_items.*') //see PS:
->get();
PS: To avoid the id attribute (or any shared name attribute between the two tables) to overlap and resulting in the wrong value, you should specify the select limit with select('user_items.*').
Well, your eager loading is probably not building the query you're expecting, and you can check it by enabling the query log.
But I would probably just use a collection filter:
$items = UserItems::where('user_id','=',$this->id)
->where('quantity','>',0)
->get()
->sortBy(function($useritem, $key) {
return $useritem->item->type;
});
You can use withAggregate function to solve your problem
UserItems::withAggregate('item','type')
->where('user_id','=',$this->id)
->where('quantity','>',0)
->orderBy('item_type')
->get();
I know it's an old question, but you can still use an
"orderByRaw" without a join.
$items = UserItems
::where('user_id','=',$this->id)
->where('quantity','>',0)
->orderByRaw('(SELECT type FROM items WHERE items.id = user_items.item_id)')
->get();
For a one to many relationship, there is an easier way. Let's say an order has many payments and we want to sort orders by the latest payment date. Payments table has a field called order_id which is FK.
We can write it like below
$orders = Order->orderByDesc(Payment::select('payments.date')->whereColumn('payments.order_id', 'orders.id')->latest()->take(1))->get()
SQL Equivalent of this code:
select * from orders order by (
select date
from payments
where order_id = payments.id
order by date desc
limit 1
) desc
You can adapt it according to your example. If I understood right, order's equivalent is user and payment's equivalent is item in your situation.
Further reading
https://reinink.ca/articles/ordering-database-queries-by-relationship-columns-in-laravel
I found another way of sorting a dataset using a field from a related model, you can get a function in the model that gets a unique relation to the related table(ex: table room related to room category, and the room is related to a category by category id, you can have a function like 'room_category' which returns the related category based on the category id of the Room Model) and after that the code will be the following:
Room::with('room_category')->all()->sortBy('room_category.name',SORT_REGULAR,false);
This will get you the rooms sorted by category name
I did this on a project where i had a DataTable with Server side processing and i had a case where it was required to sort by a field of a related entity, i did it like this and it works. More easier, more proper to MVC standards.
In your case it will be in a similar fashion:
User::with('item')->where('quantity','>',0)->get()->sortBy('item.type',SORT_REGULAR,false);
$users
->whereRole($role)
->join('address', 'users.id', '=', 'address.user_id')
->orderByRaw("address.email $sortType")
->select('users.*')
you can simply do it by
UserItems::with('item')
->where('user_id','=',$this->id)
->where('quantity','>',0)
->orderBy(
Item::select('type')
->whereColumn('items.useritem_id','useritems.id')
->take(1),'desc'
)
->get();

Laravel Order by in one to many relation with second table column

Hi i have tables with one to many relation
sectors
id
name
position
seat_plans
id
name
sector_id
I just want to select all seat plans order by sectors.position. I tried
$seat_plans = SeatPlan::with(['sector' => function($q){
$q->orderBy('position');
}
])->get();
but it is not working. when i check The SQL it is generating query like
select * from seat_plans
can anybody please tell me how to do this?
I don't think you need a custom function for your use case. Instead try this:
$users = DB::table('seat_plans')
->join('sectors', 'seat_plans.sector_id, '=', 'sectors.id')
->select('seat_plans.*')
->orderBy('sectors.position')
->get();

Resources