Order by when using union queries - laravel

I have two tables and i am trying to set 3 queries using union and order each query by created_at DESC but the probem always the data get ordered by ASC.
This code works fine if i removed the union.
I want each query to be returned ordered by created_at DESC.
Any help please ?
$first = Article::select('articles.*')->with('section_category')
->join('section_categories', 'section_categories.id', '=', 'articles.section_category_id')
->join('section_categories_value_chain', 'section_categories_value_chain.section_categories_id', '=', 'section_categories.id')
->leftJoin('article_produce as ap1', 'articles.id', '=', 'ap1.article_id')->whereNull('ap1.article_id')
->whereIn('section_categories_value_chain.value_chain_id', $c_vc_arr)
->where('articles.section_category_id', $section_id)
->where('articles.deleted_at', NULL)
->orderByDesc('articles.created_at');
$second = Article::select('articles.*')->with('section_category')
->join('section_categories', 'section_categories.id', '=', 'articles.section_category_id')
->join('section_categories_value_chain', 'section_categories_value_chain.section_categories_id', '=', 'section_categories.id')
->join('article_produce as ap2', 'articles.id', '=', 'ap2.article_id')->whereNotNull('ap2.article_id')
->whereIn('section_categories_value_chain.value_chain_id', $c_vc_arr)
->whereNotIn('ap2.produce_id', $c_p_arr)
->where('articles.section_category_id', $section_id)
->where('articles.deleted_at', NULL)
->orderByDesc('articles.created_at');
$articles = Article::select('articles.*')->with('section_category')
->join('section_categories', 'section_categories.id', '=', 'articles.section_category_id')
->join('section_categories_value_chain', 'section_categories_value_chain.section_categories_id', '=', 'section_categories.id')
->join('article_produce as ap3', 'articles.id', '=', 'ap3.article_id')->whereNotNull('ap3.article_id')
->whereIn('section_categories_value_chain.value_chain_id', $c_vc_arr)
->whereIn('ap3.produce_id', $c_p_arr)
->where('articles.section_category_id', $section_id)
->where('articles.deleted_at', NULL)
->orderByDesc('articles.created_at')
->union($second)
->union($first)
->paginate(self::paginate);

Related

Laravel Query Builder Foreach Loop how do I reference a field that exists in both join tables

The id field in the foreach loop exists in both of the tables that I am joining, I need to reference it to one table only (ie. program_types.id) in the foreach loop:
$program_details = DB::table('program_allocation')
->where('twilio_wa_from_no', '=', $tophonenumber)
->where('twilio_sid' , $account_sid)
->join('program_types', 'program_allocation.program_type', '=', 'program_types.id')
->get();
foreach ($program_details as $program) {
$program_allocation_id = $program->id;
}
You can use select('program_allocation.*', 'program_types.id AS program_type_id') to specify which columns of which tables included in query you want to use.
$program_details = DB::table('program_allocation')
->where('twilio_wa_from_no', '=', $tophonenumber)
->where('twilio_sid', $account_sid)
->join('program_types', 'program_allocation.program_type', '=', 'program_types.id')
->select('program_allocation.*', 'program_types.id AS program_type_id')
->get();
You can check it on official Laravel documentation: https://laravel.com/docs/9.x/queries#inner-join-clause
Select field and give one of the join table id an alias
$program_details = DB::table('program_allocation')
->join('program_types', 'program_allocation.program_type', '=', 'program_types.id')
->select('program_types.*', 'program_allocation.id as allocationID', )
->where('twilio_wa_from_no', '=', $tophonenumber)
->where('twilio_sid' , $account_sid)
->get();

laravel mysql -problem with data extraction

hello I learn laravel I have a problem I have a mysql database with a table breakdowns in it columns machine_name and data_zgnoszeniaawarii, I need help because I do not know how to extract data from the database in the form
machine name and number of occurrences, how to pass it to blade.php, e.g.
machine name
machine - NR01
number of appearances
5
is it something like this:
$quantity_of_of_machine =DB::select( DB::raw("SELECT numer_maszyny, COUNT(*) FROM `awaries` GROUP BY numer_maszyny") );
or
$quantity_of_of_machine = DB::table('awaries')
->select('numer_maszyny')
->groupBy('numer_maszyny')
->where('data_zgloszenia', '!=', null)
->where('user_id', '=', $user_id)
->count();
It is better if you add the table scheme, but now I can say you should do something like this:
DB::table('awaries')->selectRaw('numer_maszyny, count(*)')
->groupBy('numer_maszyny')
->where('data_zgloszenia', '!=', null)
->where('user_id', '=', $user_id); // ->get();

Counting columns with if conidition in query

Counting only columns in which, Buy_Rate is more than Sell_Rate.
My query is not resulting as per expected, it is resulting me wrong.
$user_id = Auth::user()->id;
$losing_trades_count = FinalTrade::where('user_id', '=', $user_id)->where('buy_rate', '<', 'sell_rate')->get()->count();
Inverse: If sell_rate is more than buy_rate then only, count the columns.
You can use whereColumn
$losing_trades_count = FinalTrade::where('user_id', '=', $user_id)
->whereColumn('buy_rate', '<', 'sell_rate')
->count();
Also there is no need to call get() when you need count() from query builder
laravel eloquent where don't support comparing columns. so you need use raw SQL in order to compair two columns. you can do something like,
$user_id = Auth::user()->id;
$losing_trades_count = FinalTrade::where('user_id', '=', $user_id)->whereRaw('buy_rate < sell_rate')->get()->count();
hope this helps!

Laravel Query Builder Stop working after groupBy

$records = DB::table('history as a')
->join('reservation2 as b', function($join){
$join->on('a.id', '=', 'b.id')
->on('a.sid', '=', 'b.sid');
})
->whereBetween('a.date', [$sDate, $eDate])
->select('a.*', DB::raw('SUM(a.perday) AS revenue'), 'b.name', 'b.checkin', 'b.checkout', 'b.status')
->groupBy('a.id')
->groupBy('a.sid')
->toSql();
Gives me following query:
select `a`.*, SUM(a.perday) AS revenue, `b`.`name`, `b`.`checkin`, `b`.`checkout`,
`b`.`status`
from `history` as `a`
inner join `reservation2` as `b` on `a`.`id` = `b`.`id` and `a`.`sid` = `b`.`sid`
where `a`.`date` between ? and ? group by `a`.`id`, `a`.`sid`
Many records are displayed if query is passed from mysql command prompt but if I replace ->toSql() with ->get() it does not give me any record.
What is the problem?

Convert raw SQL to use Eloquent Query Builder

How can I convert the following complex SQL query to use the Eloquent query builder? I want to use methods such as join() and where(), get() etc.
The below query returns a list of locations along with counts for vouchers that have been redeemed.
select
a.location_name,
'' as dates,
a.places,
sum(netvalue155),
sum(netvalue135) from
(
select
l.id,
l.location_name,
b.places,
case when v.net_value = 155 then 1 else 0 end as netvalue155,
case when v.net_value = 135 then 1 else 0 end as netvalue135
from locations l
left join bookings b on l.id = b.location_id
left join vouchers v on b.voucher_code = v.voucher_code
) a
right join locations l on l.id = a.id
group by a.location_name
EDIT
I am trying the below code, which throws the error SQLSTATE[42S22]: Column not found: 1054 Unknown column 'sub.id' in on clause
$subQuery = DB::table('locations')
->select(
'locations.id',
'locations.location_name',
DB::raw('"'.$request->get('dates').'" as dates'),
DB::raw('sum(bookings.id) as number'),
DB::raw('round(sum(bookings.final_price/1.2), 2) as paidbycard'),
DB::raw('case when bookings.voucher_value = 155 then round(sum(bookings.voucher_value/1.2), 2) else 0.00 end as voucher155'),
DB::raw('case when bookings.voucher_value = 135 then round(sum(bookings.voucher_value/1.2), 2) else 0.00 end as voucher135'),
DB::raw('case when bookings.transfer_fee = 10 then round(sum(bookings.transfer_fee/1.2), 2) else 0.00 end as transfer_fee'))
->leftJoin('bookings', 'locations.id', '=', 'bookings.location_id');
$meatBookQuery = DB::table('orders')->select(DB::raw('sum(orders_items.price) as total'))
->join('orders_items', 'orders.id', '=', 'orders_items.order_id')
->where('orders_items.item_name', 'The Meat Book');
$booking = DB::table(DB::raw("({$subQuery->toSql()}) as sub, ({$meatBookQuery->toSql()}) as meatBook"))
->mergeBindings($subQuery)
->mergeBindings($meatBookQuery)
->select('sub.location_name', 'sub.dates', 'sub.number', 'sub.paidbycard', 'sub.voucher155', 'sub.voucher135', 'sub.transfer_fee', DB::raw('round(sum(sub.voucher155 + sub.voucher135 + sub.transfer_fee + sub.paidbycard), 2) as total'), 'meatBook.total')
->leftJoin('locations', 'locations.id', '=', 'sub.id')
->leftJoin('bookings', 'bookings.location_id', '=', 'sub.id')
->groupBy('sub.location_name');
First of all
I often see people asking for how to rebuild a complex SQL query in Laravels Query Builder. But not every operation which is possible in SQL or MySQL is implemented as a function in Laravels Query Builder. This means you can't rebuild every SQL query in Query Builder without using raw SQL.
What does this mean for your SQL query?
Some things like sub queries (the from (select ...) part) and the case when ... part is not implemented in Query Builder. At least therefore you will have to use the raw expression with the DB::raw() function. I'm not sure about the sum() if this is already possible but you will surely find that in the docs.
Other things like joins are implemented as a function:
$users = DB::table('users')
->join('contacts', 'users.id', '=', 'contacts.user_id')
->join('orders', 'users.id', '=', 'orders.user_id')
->select('users.id', 'contacts.phone', 'orders.price')
->get();
see Laravel Documentation: Queries - Joins
And you can even mix up Query Builder functions with raw expressions:
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();
see Laravel Documentation: Queries - Raw Expression
Example for a sub query:
$subQuery = DB::table('locations')
->leftJoin('bookings', 'locations.id', '=', 'bookings.location_id')
->leftJoin('vouchers', 'bookings.voucher_code', '=', 'vouchers.voucher_code')
->select('locations.id', 'locations.location_name', 'bookings.places');
$query = DB::table(DB::raw("({$subQuery->toSql()} as sub"))
->mergeBindings($subQuery)
->select(...)
->rightJoin(...)
->groupBy('sub.location_name')
->get();
So you can rebuild some parts of the query in Query Builder and use raw expressions wherever you need to.
To debug a query while you build it Laravels query logging function can be very helpful.

Resources