get only the selected column from the join table - php

I have this reference code below, first the line 1 will get
$aa = users_details::select(array('id', 'user_id'))->where('id', '=', $request->id)->first(); //first line
$bb = User::select(array('user_id'))->where('user_id', '=', $aa->id)->with('user_details')->first(); //second line
the first line returns 13 which is correct while the second line returns 'null' which it should not because there's actually a record that has a user_id of '13'. Any ideas, help please?
and also is there a way I could select only selected columns in this join table (Eloquent relationship hasOne)
$bb = User::select(array('user_id'))->where('user_id', '=', $aa->id)->with('user_details')->first();
I dont know if
select(array('user_id'))
is the right one to select only selected columns from the join table. Any ideas, help, please?

First Question:
$bb = User::select(array('user_id'))->where('user_id', '=', $aa->id)->with('user_details')->first();
Do you have user_id column in users (or anywhere User Model refers to) table? Do you have user_details method in User model?
Second Question:
You can select as
User::select('user_id', 'username', 'sex')
If you have same column name in the joined table, then you can select as
User::select('users.user_id as a', 'users.username', 'users.sex', 'user_details.user_id as b')
UPDATE:
How can I select only selected column from the 'user_details' when
both is joining togehter?
User::select('users.user_id as user_id', 'users.username', 'users.sex', 'user_details.user_id as user_details_id')->join('user_details','user_details.user_id','=', 'users.id' )->where('users.id', '=', $aa->id)->first();
To select the columns from the joined table, just prefix the column name with table name such as user_details.user_id.

Related

Laravel OrderBy by related table column

I have a table (A) that has a One to Many relation with another table (B).
I want to query Table A and eager load Table B with the Table A results - but I also want to sort Table A by a value in Table B.
I have tried using OrderBy in the query and also trying SortBy on the resultant collection but cannot get the Table A data to be sorted by the value found in Table B.
Example of what I have tried:
$query = ModelA::with("ModelB"])->get()->sortByDesc('ModelB.sortValue');
Keep in mind, I am only interested in the LATEST record from Table B. So I need to query Table A and sort by a value in the LATEST records of Table B.
How can I achieve this?
EDIT:
The below (as suggested by #ljubadr) works pretty close, but the issue is that there are many record in Table B which means that it doesn't reliably sort as it doesn't seem to sortby the latest records in Table B. Can I have the join return ONLY the latest record for each ID?
$query = ModelA::select('TableA.*')
->join('TableB', 'TableA.id', '=', 'TableB.col_id')
->groupBy('TableA.id')->orderBy('TableB.sortCol', 'desc')
->with(['x'])
->get();
EDIT 2:
#Neku80 answer has gotten me closest but it seems to not sort the column with the greatest accuracy.. I'm sorting a Decimal column and for the most part it is in order but in some places the items are out of order..
$latestTableB = ModelB::select(['TableA_id', 'sortByColumnName'], DB::raw('MAX(created_at) as created_at'))
->groupBy('TableA_id');
$query = ModelA::select('TableA.*')
->joinSub($latestTableB, 'latest_TableB', function ($join) {
$join->on('TableA.id', '=', 'latest_TableB.TableA_id');
})
->orderBy('latest_TableB.sortByColumnName')
->get();
For example, the ordering is like:
0.0437
0.0389
0.0247 <-- -1
0.025 <-- +1
0.0127
When I delete all rows except for the 'latest' rows, then it orders correctly, so it still must be ordering with old data...
I have found a solution:
ModelA::select('TableA.*', 'TableB.sortByCol as sortByCol')
->leftJoin('TableB', function ($query) {
$query->on('TableB.TableA_id', '=', 'TableA.id')
->whereRaw('TableB.id IN (select MAX(a2.id) from TableB as a2 join TableA as u2 on u2.id = a2.TableA_id group by u2.id)');
})
->orderBy('TableB.sortByCol')
->get();
Another alternative to order is like this:
$users = User::orderBy(
Company::select('name')
->whereColumn('companies.user_id', 'users.id'),
'asc'
)->get();
Here we are ordering in asc order by company name field.
In this article it is explained in detail.
You can simply execute a left join query:
ModelA::query()->leftJoin('model_b_table', 'model_a_table.primary_key', '=', 'model_b_table.foreign_key')->orderBy('model_a_table.target_column')->get();
This should work if you only need TableB's ID and created_at columns:
$latestTableB = ModelB::select('TableA_id', DB::raw('MAX(created_at) as created_at'))
->groupBy('TableA_id');
$query = ModelA::select('TableA.*')
->joinSub($latestTableB, 'latest_TableB', function ($join) {
$join->on('TableA.id', '=', 'latest_TableB.TableA_id');
})
->orderBy('latest_TableB.created_at')
->get();

getting joined tables id instead main table in blade

Do I need to specify main table's name in order to get that tables id instead joined table's id , My codes are (from controller ) :
public function RegistrationEditView(Request $r,$id){
$data=DB::table('bootcamp_users')->leftJoin('countries_detailed', function($join) {
$join->on('countries_detailed.id', '=', 'bootcamp_users.country_id');
})->where('bootcamp_users.id',$id)->first();
$course_lists=DB::table('course_languages')->get();
$bootcamps=DB::table('bootcamp_users')->get();
return view('admin.registeredBootcamp.edit',compact('data','course_lists','bootcamps'));
}
That's because the default SELECT behaviour of Laravel's query builder is SELECT * so any column sharing the same name in a joined table will overwrite the original selected table's columns: that's why you see countries_detailed.id instead of bootcamp_users.id.
I suggest specifying a custom select statement to only select needed columns from both tables, for example:
$data = DB::table('bootcamp_users')
->select(['bootcamp_users.id', /* Add all needed columns here */])
->leftJoin('countries_detailed', function($join) {
$join->on('countries_detailed.id', '=', 'bootcamp_users.country_id');
})->where('bootcamp_users.id',$id)->first();

Inside join make if condition and get details in laravel

I tried to match two columns and if it was matching based on the id i'll assign username to that matched column. but inside join i can't make if condition on joining table.
$list = DB::table('job')
->join('users', 'users.id', '=', 'job.created_by')
->select('job.*','users.first_name as created_by','users.first_name')
->where('job.enterprise_id', $user->id)
->get();
In my json i had one value updated_by with value 1 means i can match with id column if it was matching i will display updated_by = first_name otherwise updated_by = null.
To show the name of user who updated job you can use a left join to users table.
$list = DB::table('job as j')
->join('users as u1', 'u1.id', '=', 'j.created_by')
->leftJoin('users as u2', 'j.updated_by' , '=', 'u2.id')
->select('j.*','u1.first_name as created_by','u2.first_name as updated_by')
->where('j.enterprise_id', $user->id)
->get();
If job was updated u2.first_name will return the name of user who updated that job if job is not update you will have a null value against u2.first_name. Also i assume you job table has a column named as updated_by which stores this information.

mysql select all from table but change column name of only one

I need to select a table which contains id, name and some more. Now i want to select everything, but just change the column name 'name' to 'user_name'. How can i do this without selecting and declaring everything?
I tried it like this, but this is not working.
return $query
->select(
'user.*',
'user.name as user_name'
)
Your issue starts from your joins. Because you join without aliasing, then the second one overwrites the first. I give you a sample query to show how you can alias your joined table, and thus alias the 'name' from the second table. Sample code:
$query = DB::table('users')
->leftjoin('users as child', 'users.id', '=', 'users.parent_id')
->select('users.*', 'child.name as child_name')
->get();

Join tables with equal columns

I have two tables users and cars, the cars has a column owner that is the id of an user and I need to join them. Both users and cars has a column called name and it's overriding. I want to keep both but with different names, like car_name and user_name on the return.
Here is how I'm doing:
$columns = [
DB::raw('cars.name as car_name')
];
$cars = Cars::join('users', 'users.id', '=', 'cars.owner')->get($columns);
It works if I try to print car_name but it still overriding the name and if I print name it still returns the name of the user instead of the car.
Is there a way for doing this right?
You can use the select() clause directly in your query.. no need to use DB::raw():
$cars = Cars::join('users', 'users.id', '=', 'cars.owner')
->select('*','cars.name as car_name')
->get();
The problem with this is that you will end up with a repeated column as you are asking the DB for everything, plus the field with a new name. That may not be a problem for you, but might be better to specify explicitly the fields you want to select:
$cars = Cars::join('users', 'users.id', '=', 'cars.owner')
->select('users.name as user_name','cars.name as car_name', 'whatever_else')
->get();
I don't think you can do what you want with gets - but you can with select. This should hopefully work:
$columns = [
'*',
'users.name as user_name',
'cars.name as car_name'
];
$cars = Cars::join('users', 'users.id', '=', 'cars.owner')->select($columns)->get();

Categories