Yii2 query all get value in join - php

I have an database with tablenames like this: tbl_accessoires_1, tbl_accessoires_2 etc. In my main table is a column that gives me the number for the table I have to join. But how do I get this value if I use ->all().
This is my query:
$query = (new Query())
->select([
'a.id id',
'a.soort soort',
])
->from('auto_new a')
->leftJoin('tbl_accessoires_--soort-- acc', 'acc.id = a.id')
->all();
So the a.soort in the select must be at the --soort--
Is there any way to do this?
If I only get one car it is possible because I could get the soort value before this query. but how do I do this when I want to get all cars

So because it's not possible in my situation I've just made a new query to get the options. This will do for now because I don't really need the options when I get all cars.

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

Using Laravel's WhereIn to search multiple tables

I have 3 SQL tables.
clients
events
client_events
Because a client can have multiple events, I made the third table to show those relationships. I am using the following code to retrieve all of the clients that have the have a record matching this event, but it is only returning 1 record when there are multiple.
$eventHosts = DB::table('clients')->whereIn('id', function($query) {
$query->select('client_id')->from('client_events')->where('event_id', '=', explode('/', $_SERVER['REQUEST_URI'])[2]);
})->get();
What am I overlooking?
You can fetch the ids first, then pass to the whereIn query.
$clientIds = DB::table('client_events')
->where('event_id', explode('/', $_SERVER['REQUEST_URI'])[2])
->pluck('client_id')
->toArray();
$eventHosts = DB::table('clients')->whereIn('id', $clientIds)->get();
To get the results in a single query and more efficeintly, try join
$eventHosts = DB::table('clients') //select your main table
->join('client_events','client_events.client_id','=','clients.id') //join it on related columns
->where('client_events.client_id',explode('/', $_SERVER['REQUEST_URI'])[2])) //apply your condition on client_events
->get();

How to alias a left joined table in laravel eloquent

Basically I have a situation where I made two left outer joins in my laravel query and now I want to select two columns and put one alias for them, if one column is null use the other columns value for that new aliased column. Something like NVL in SQL. Any suggestions?
I tried something like ...->select('one or other as newName'); but it won't work.
Edit: I have a table for articles that I join with user, news_groups and magazine_groups. Article that has news_group won't have magazine_group. I want to show those together in one joined column in select using alias.
DB::table('articles')
->leftJoin('articles', 'articles.id', '=', 'articles.user_id')
->leftJoin('news_groups', 'news_groups.id', '=', 'articles.news_group_id')
->leftJoin('magazine_groups', 'magazine_groups.id', '=', 'articles.magazine_groups_id')
->select('articles.id', 'type', 'title', 'articles.published_at',
'users.first_name','users.last_name', 'news_groups.name or magazine_groups.name as group_name')
->groupBy('articles.id');
You are going to need to use a Raw Expression:
DB::table('articles')
->leftJoin('articles', 'articles.id', '=', 'articles.user_id')
->leftJoin('news_groups', 'news_groups.id', '=', 'articles.news_group_id')
->leftJoin('magazine_groups', 'magazine_groups.id', '=', 'articles.magazine_groups_id')
->select(DB::raw('articles.id, type, title, articles.published_at, users.first_name, users.last_name, COALESCE(news_groups.name, magazine_groups.name) as group_name'))
->groupBy('articles.id');
Take a look at https://laravel.com/docs/5.6/queries#raw-expressions Raw expressions.
You might try something like this :
->select(DB::RAW('IFNULL(news_groups.name,magazine_groups.name) AS groupname,articles.id..other selects'))

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

Column Name Conflict on Laravel 4 Fluent Query Builder

I have a query like this:
$users = DB::table('users')->join('user_roles','users.role_id','=','user_roles.id')->get();
and a table that has a column id (users.id) and another table that has columns id and user_id (user_roles.id & user_roles.user_id),
but the problem is.. what is being returned on $user->id is the user_roles.id instead of the users.id column.. how do i fix this so that what i get is not the role id but the user id instead..
thanks!
Found it!
using ->select('users.*', 'user_roles.role_name') i was able to remove user_roles.id from the returned values and thus eliminating the conflict.
Here is the final query:
$users = DB::table('users')->join('user_roles','users.role_id','=','user_roles.id')->select('users.*', 'user_roles.role_name')->get();
The better way to do this is using 'as':
$users = DB::table('users')->join('user_roles','users.role_id','=','user_roles.id')->get(array('users.*', '**user_roles.id as user_roles_id**', 'user_roles.*'));

Categories