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'))
Related
I am trying to left join a table in Eloquent Query Builder but the table has two potential foreign keys. I only want to join once but if a potential other column is not null, then it should take presedence.
DB::connection('...')->table('some_table')
->leftJoin('table_that_should_take_presedence as ttstp', 'ttstp.id', '=', 'some_table.ttstp_id')
->leftJoin('some_other_table', function ($otherTable) {
$otherTable->on('some_other_table.id', '=', 'ttstp.some_other_table_id');
//->.... if ttstp.some_other_table_id does not exist then
// some_table.some_other_table_id should be used
});
So far, my solution is to join the table twice and use a coalesce to enable that presedence:
DB::connection('...')->table('some_table')
->selectRaw('coalesce(sot.example, sot2.example, null) as example')
->leftJoin('table_that_should_take_presedence as ttstp', 'ttstp.id', '=', 'some_table.ttstp_id')
->leftJoin('some_other_table as sot', 'sot.id', '=', 'ttstp.some_other_table_id');
->leftJoin('some_other_table as sot2', 'sot2.id', '=', 'some_table.some_other_table_id');
This doesn't seem slick, I feel the optimal solution is joining once. Any help appreciated. Thanks in advance.
As I understand you correct, you want this:
$q = DB::connection('...')
->table('some_table')
->selectRaw('sot.example')
->leftJoin('table_that_should_take_presedence as ttstp', 'ttstp.id', '=', 'some_table.ttstp_id')
// Try to join by ttstp.some_other_table_id column, if it's null then use some_table.some_other_table_id column
->leftJoin('some_other_table as sot', 'sot.id', '=', DB::raw('COALESCE(ttstp.some_other_table_id, some_table.some_other_table_id)'));
dump($q->toSql());
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();
I'm trying to fetch following things from the database:
user name
user avatar_name
user avatar_filetype
complete conversation_messages
with the following query:
static public function getConversation($id)
{
$conversation = DB::table('conversation_messages')
->where('belongsTo', $id)
->join('users', 'conversation_messages.sender', '=', 'users.id')
->join('user_avatars', 'conversation_messages.sender', '=', 'user_avatars.id')
->select('users.name', 'conversation_messages.*', 'user_avatars.name', 'user_avatars.filetype')
->get();
return $conversation;
}
It works fine so far, but the avatar's column name is 'name' like the column name from the 'users' table.
So if I'm using this query the to get the output via $conversation->name, the avatar.name overwrites the users.name
Is there a way to rename the query output like the mysql "as" feature at laravel 5.1?
For example:
$conversation->avatarName
$conversation->userName
Meh okay.. i've found a simple solution here
->select('users.name as userName', 'conversation_messages.*', 'user_avatars.name as avatarName', 'user_avatars.filetype')
As you can mention I've added the requested "as-Feature" next to the table.columnName
Take a look at this example of trying to join three tables staffs, customers and bookings(pivot table).
$bookings = \DB::table('bookings')
->join('staffs', 'staffs.id' , '=', 'bookings.staff_id')
->join('customers', 'customers.id' , '=', 'bookings.customer_id')
->select('bookings.id', 'bookings.start_time', 'bookings.end_time', 'bookings.service', 'staffs.name as Staff-Name', 'customers.name as Customer-Name')
->orderBy('customers.name', 'desc')
->get();
return view('booking.index')
->with('bookings', $bookings);
I had the following problem, simplified example:
$result = Donation::join('user', 'user.id', '=', 'donation.user_id')->where('user.email', 'hello#papabello.com')->first();
$result is a collection of Donation models. BUT CAREFUL:
both tables, have a 'created_at' column. Now which created_at is displayed when doing $result->created_at ? i don't know. It seems that eloquent is doing an implicit select * when doing a join, returning models Donation but with additional attributes. created_at seems random. So what I really wanted, is a return of all Donation models of the user with email hello#papabello.com
solution is this:
$result = Donation::select('donation.*')->join('user', 'user.id', '=', 'donation.user_id')->where('user.email', 'hello#papabello.com')->first();
Yeah, simply rename the column on either table and it should work.
Also what you can do is, rename the user.name column to anything, also rename sender column of conversation_messages to id and perform a natural join.
I'm new to laravel and I have some issues with the query builder.
The query I would like to build is this one:
SELECT SUM(transactions.amount)
FROM transactions
JOIN categories
ON transactions.category_id == categories.id
WHERE categories.kind == "1"
I tried building this but it isn't working and I can't figure out where I am wrong.
$purchases = DB::table('transactions')->sum('transactions.amount')
->join('categories', 'transactions.category_id', '=', 'categories.id')
->where('categories.kind', '=', 1)
->select('transactions.amount')
->get();
I would like to get all the transactions that have the attribute "kind" equal to 1 and save it in a variable.
Here's the db structure:
transactions(id, name, amount, category_id)
categories(id, name, kind)
You don't need to use select() or get() when using the aggregate method as sum:
$purchases = DB::table('transactions')
->join('categories', 'transactions.category_id', '=', 'categories.id')
->where('categories.kind', '=', 1)
->sum('transactions.amount');
Read more: http://laravel.com/docs/5.0/queries#aggregates
If one needs to select SUM of a column along with a normal selection of other columns, you can sum select that column using DB::raw method:
DB::table('table_name')
->select('column_str_1', 'column_str_2', DB::raw('SUM(column_int_1) AS sum_of_1'))
->get();
You can get some of any column in Laravel query builder/Eloquent as below.
$data=Model::where('user_id','=',$id)->sum('movement');
return $data;
You may add any condition to your record.
Thanks
MyModel::where('user_id', $_some_id)->sum('amount')
I'm trying to combine two tables based on if they match a given pair in a many-to-many relation. I already know the SQL statement I'm trying to produce, which is functionally equivalent to the following:
SELECT columnA, columnB, ...
...
JOIN matching_table
ON ( (matching_table.id1 = table_a.id AND matching_table.id2 = table_b.id) OR
(matching_table.id1 = table_b.id AND matching_table.id2 = table_a.id) )
...
But I want to produce it using Kohana's query builder for consistency. The problem is I can't seem to find a way of creating a complex ON query. So far all I've got is
DB::select('columnA', 'columnB', ...)
...
->join('matching_table')
->on('matching_table.id1', '=', 'table_a.id')
->on('matching_table.id2', '=', 'table_b.id')
...
and this generates the first AND sequence but I can't seem to put it together with an OR.
Any suggestions?
You should be able to use where instead of on (not tested though):
->join('matching_table')
->where_open()
->where('matching_table.id1', '=', 'table_a.id')
->and_where('matching_table.id2', '=', 'table_b.id')
->where_close()
->or_where_open()
->where('matching_table.id1', '=', 'table_b.id')
->and_where('matching_table.id2', '=', 'table_a.id')
->or_where_close()