Laravel - Merge multiple queries as one with each as a column - laravel

I have four different queries I want to combine as on queries, with each representing a column. Each stand for just only one row, because of the count(), sum() functions
I have written the queries
$lastsevendayssubscribers = DB::table('users')
->select(DB::raw('count(*) as total ') )
->where(DB::raw("DATE(created_at)"), '>=', DB::raw('DATE(NOW()) - INTERVAL 7 DAY'))
->count();
$activesubscriptions = DB::table('users')
->where('plan_status', 1)
->count();
$expiredsubscriptions = DB::table('users')
->where('plan_status', 1)
->count();
$currentDay = date('m');
$currentdaybilling = DB::table("users")
->select(DB::raw("SUM(amount) as total"))
->whereRaw('(created_at) = ?',$currentDay)
->get();
I want the final result to look like this:
|$lastsevendayssubscribers|$activesubscriptions|$expiredsubscriptions|$currentdaybilling|

Related

Order by when using union queries

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

Eloquent Sum Timestampdiff with relation

Is it possible to get sum from timestampdiff in single query including With(relation)?
This is what i have so far:
$totalLate = Attendance::select('eid', DB::raw('DATE_FORMAT(attendance_time, "%H:%i:00") as att_time'))
->with(['employee.shift' => function ($query) {
$query->select('id','shift_start as shf');
}])
->where('eid',$id)
->whereRaw('MONTH(attendance_time) = ?', [$requestMonth])
->whereRaw('YEAR(attendance_time) = ?', [$requestYear])
->where('late', 'yes')
->sum(DB::raw('TIMESTAMPDIFF(MINUTE, shf, att_time)'));
For now i can get both time(shf and att_time) but not the sum of the diff.
Or i have to separate the query?

Refactor Laravel Query

I have a query that I have built, and I am trying to understand how I can achieve the same thing but in one single query. I am fairly new to Laravel and learning. Anyway someone could help me understand how I can achieve what I am after?
$activePlayerRoster = array();
$pickupGames = DB::table('pickup_games')
->where('pickupDate', '>=', Carbon::now()->subDays(30)->format('m/d/Y'))
->orderBy('pickupDate', 'ASC')
->get();
foreach ($pickupGames as $games) {
foreach(DB::table('pickup_results')
->where('pickupRecordLocatorID', $games->recordLocatorID)
->get() as $activePlayers) {
$activePlayerRoster[] = $activePlayers->playerID;
$unique = array_unique($activePlayerRoster);
}
}
$activePlayerList = array();
foreach($unique as $playerID) {
$playerinfo = DB::table('players')
->select('player_name')
->where('player_id', $playerID)
->first();
$activePlayerList[] = $playerinfo;
}
return $activePlayerList;
pickup_games
checkSumID
pickupDate
startTime
endTime
gameDuration
winningTeam
recordLocatorID
pickupID
1546329808471
01/01/2019
08:03 am
08:53 am
50 Minute
2
f47ac0fc775cb5793-0a8a0-ad4789d4
216
pickup_results
id
checkSumID
playerID
team
gameResult
pickOrder
pickupRecordLocatorID
1
1535074728532
425336395712954388
1
Loss
0
be3532dbb7fee8bde-2213c-5c5ce710
First, you should try to write SQL query, and then convert it to Laravel's database code.
If performance is not critical for you, then it could be done in one query like this:
SELECT DISTINCT players.player_name FROM pickup_results
LEFT JOIN players ON players.player_id = pickup_results.playerID
WHERE EXISTS (
SELECT 1 FROM pickup_games
WHERE pickupDate >= DATE_FORMAT(SUBDATE(NOW(), INTERVAL 30 DAY), '%m/%d/%Y')
AND pickup_results.pickupRecordLocatorID = recordLocatorID
)
Here I'm assuming you know what you're doing with this dates comparison, because it looks weird to me.
Now, let's convert it to Laravel's code:
DB::table('pickup_results')
->select('players.player_name')->distinct()
->leftJoin('players', 'players.player_id', '=', 'pickup_results.playerID')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('pickup_games')
->where('pickupDate', '>=', Carbon::now()->subDays(30)->format('m/d/Y'))
->whereRaw('pickup_results.pickupRecordLocatorID = recordLocatorID');
})
->get();
Basically, I would reduce the query to its SQL variant to get directly at its core.
The essence of the query is
select `x` FROM foo WHERE id IN (
select distinct bar.id from bar join baz on bar.id = baz.id);
This can be interpreted in Eloquent as:
$thirtyDaysAgo = Carbon::now()->subDays(30)->format('m/d/Y');
$playerIds = DB::table('pickup_games')
->select('pickup_games.player_id')
->join(
'pickup_results',
'pickup_results.pickupRecordLocatorID',
'pickup_games.recordLocatorID')
->where('pickupDate', '>=', $thirtyDaysAgo)
->orderBy('pickupDate', 'ASC')
->distinct('pickup_games.player_id');
$activePlayers = DB::table('players')
->select('player_name')
->whereIn('player_id', $playerIds);
//>>>$activePlayers->toSql();
//select "player_name" from "players" where "player_id" in (
// select distinct * from "pickup_games"
// inner join "pickup_results"
// on "pickup_results"."pickupRecordLocatorID" = "pickup_games"."recordLocatorID"
// where "pickupDate" >= ? order by "pickupDate" asc
//)
From the resulting query, it may be better to refactor the join as relationship between the Eloquent model for pickup_games and pickup_results. This will help to further simplify $playerIds.

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!

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