Laravel - Combine multiple queries as one and also include GroupBy - laravel

I have written different queries that function for different things. I want to combine them as one (Sales for: Today, Current Week, Current Week, Current Month, Current Year and Overall Sales) and Group By a field called store.
$currentYear = date('y');
$currentyearbilling = DB::table("billings")
->select(DB::raw("SUM(amount) as total"))
->whereRaw('YEAR(created_at) = ?',$currentYear)
->get();
$currentMonth = date('m');
$currentmonthbilling = DB::table("billings")
->select(DB::raw("SUM(amount) as total"))
->whereRaw('MONTH(created_at) = ?',$currentMonth)
->get();
$currentWeek = date('w');
$currentweekbilling = DB::table("billings")
->select(DB::raw("SUM(amount) as total"))
->whereRaw('WEEK(created_at) = ?',$currentWeek)
->get();
$currentDay = date('d');
$currentdaybilling = DB::table("billings")
->select(DB::raw("SUM(amount) as total"))
->whereRaw('(created_at) = ?',$currentDay)
->get();
Group By store.
The table name is called billings. I still want to follow this format
DB::table("billings")
How do I achieve this?
Error:

You should try this:
$currentYear = date('y');
$currentMonth = date('m');
$currentWeek = date('w');
$currentDay = date('d');
$currentyearbilling = DB::table("billings")
->select(DB::raw("SUM(amount) as total"))
->whereRaw('YEAR(created_at) = ?',$currentYear)
->orWhereRaw('MONTH(created_at) = ?',$currentMonth)
->orWhereRaw('WEEK(created_at) = ?',$currentWeek)
->orWhereRaw('(created_at) = ?',$currentDay)
->groupBy('store')
->get();

Lets say we have a table billings like this:
| column | type |
|------------|------------|
| id | int |
| store | varchar |
| amount | int |
| created_at | timestamps |
| updated_at | timestamps |
I will get amount of every store in current_day, current_month, current_week, current_year, and overall by using sub query like this:
select
store,
(SELECT SUM(amount) from billings as child where child.store = parent.store and DAY(created_at) = ? and MONTH(created_at) = ? and YEAR(created_at) = ?) as current_day,
(SELECT SUM(amount) from billings as child where child.store = parent.store and WEEK(created_at) = ?) as current_week,
(SELECT SUM(amount) from billings as child where child.store = parent.store and MONTH(created_at) = ? and YEAR(created_at) = ?) as current_month,
(SELECT SUM(amount) from billings as child where child.store = parent.store and YEAR(created_at) = ?) as current_year,
SUM(amount) as overall,
COUNT(id) as total_rows
from billings as parent
group by store
And with Eloquent, it would be just something like this:
$childQuery = \DB::table(\DB::raw('billings as child'))
->select(\DB::raw('SUM(amount) as amount'))
->whereRaw('child.store = parent.store');
$currentDayQuery = (clone $childQuery)->whereDay('created_at', now()->day)->whereMonth('created_at', now()->month)->whereYear('created_at', now()->year);
$currentWeekQuery = (clone $childQuery)->where(\DB::raw('WEEK(created_at)'), now()->weekOfYear);
$currentMonthQuery = (clone $childQuery)->whereMonth('created_at', now()->month);
$currentYearQuery = (clone $childQuery)->whereYear('created_at', now()->year);
$rows = \DB::table(\DB::raw('billings as parent'))
->select([
'store',
\DB::raw('(' . $currentDayQuery->toSql() . ') as current_day'),
\DB::raw('(' . $currentWeekQuery->toSql() . ') as current_week'),
\DB::raw('(' . $currentMonthQuery->toSql() . ') as current_month'),
\DB::raw('(' . $currentYearQuery->toSql() . ') as current_year'),
\DB::raw('SUM(amount) as overall'),
\DB::raw('COUNT(id) as total_rows')
])
->mergeBindings($currentDayQuery)
->mergeBindings($currentWeekQuery)
->mergeBindings($currentMonthQuery)
->mergeBindings($currentYearQuery)
->groupBy('store')
->get();
Hope this helps.

Related

How to Convert this Query to Eloquent or Query Builder?

I have a query like this. How should I convert it into a eloquent or query builder
SELECT
x.MATERIAL_ID,
(SELECT TAPET_NAME FROM MA_TAPE_TYPE WHERE TAPET_CODE = x.MATERIAL_TYPE) as media_type,
(SELECT TAPEF_NAME FROM MA_TAPE_FORMAT WHERE TAPEF_CODE = x.MATERIAL_FORMAT) as media_format,
STOCK_MATERIAL_EPI.HOUSE_NO,
x.TXN_DATE,
STOCK_MATERIAL_EPI.PROGRAM_NAME,
CASE WHEN x.iden_flag = 'P' THEN STOCK_MATERIAL_EPI.epi_title WHEN x.iden_flag = 'C'
THEN STOCK_MATERIAL_EPI.prod_version_name WHEN x.iden_flag = 'M' THEN STOCK_MATERIAL_EPI.promo_name
END as episode_title,
PUR_EPISODE_HDR.EPI_NO,
(SELECT MAX (last_date) FROM run_master WHERE run_master.row_id_epi = PUR_EPISODE_HDR.row_id AND
run_master.run_aired = 'Y') as last_tx,
x.REMARKS,
x.LOCATION_ID as shelf_no,
stock_material_slag.remarks as short_list
FROM STOCK_MATERIAL x
LEFT JOIN STOCK_MATERIAL_EPI ON x.MATERIAL_ID = STOCK_MATERIAL_EPI.MATERIAL_ID
LEFT JOIN stock_material_slag ON x.MATERIAL_ID = stock_material_slag.MATERIAL_ID
LEFT JOIN PUR_EPISODE_HDR ON STOCK_MATERIAL_EPI.ROW_ID_EPI = PUR_EPISODE_HDR.ROW_ID
I'm confused as to how to convert them. Can someone help me.
I tried to write like this.
But it doesn't work,
$materials = DB::connection('oracle')
->table('STOCK_MATERIAL AS x')
->select('x.MATERIAL_ID',
DB::raw("(SELECT TAPET_NAME FROM MA_TAPE_TYPE WHERE TAPET_CODE = x.MATERIAL_TYPE) as MEDIA_TYPE"),
DB::raw("(SELECT TAPEF_NAME FROM MA_TAPE_FORMAT WHERE TAPEF_CODE = x.MATERIAL_FORMAT) as MEDIA_FORMAT"),
'x.TXN_DATE',
'y.HOUSE_NO', 'y.PROGRAM_NAME',
DB::raw("(CASE WHEN x.IDEN_FLAG = 'P' THEN z.EPI_TITLE WHEN x.IDEN_FLAG = 'C' THEN z.PROD_VERSION_NAME WHEN x.IDEN_FLAG = 'M' THEN z.PROMO_NAME END as EPISODE_TITLE)"),
'w.EPI_NO',
DB::raw("(SELECT MAX (LAST_DATE) FROM RUN_MASTER WHERE RUN_MASTER.ROW_ID_EPI = w.ROW_ID AND RUN_MASTER.RUN_AIRED = 'Y') as LAST_TX"),
'z.REMARKS',
'x.LOCATION_ID as SHELF_NO',
'z.REMARKS'
)
->leftJoin('STOCK_MATERIAL_EPI AS y', 'y.MATERIAL_ID', '=', 'x.MATERIAL_ID')
->leftJoin('STOCK_MATERIAL_SLAG AS z', 'z.MATERIAL_ID', '=', 'x.MATERIAL_ID')
->leftJoin('PUR_EPISODE_HDR AS w', 'w.ROW_ID', '=', 'y.ROW_ID_EPI')
What else do I write right?
You would need to define eloquent models and then use with(). Documentation can be found at the link below: https://laravel.com/docs/7.x/eloquent-relationships#constraining-eager-loads
example
StockMaterial::with([
'maTapeType' => function($query) {
$query->get('name')
})
])
For Query Builder you DB::raw and DB::leftJoin to create the same query.
DB::from('STOCK_MATERIAL')
->selectRaw([
'TAPET_NAME as media_type',
'CASE WHEN x.iden_flag = "P" THEN STOCK_MATERIAL_EPI.epi_title
WHEN x.iden_flag = "C" THEN STOCK_MATERIAL_EPI.prod_version_name
WHEN x.iden_flag = "M" THEN STOCK_MATERIAL_EPI.promo_name
END as episode_title',
])
->leftJoin('MA_TAPE_TYPE', 'TAPET_CODE', 'STOCK_MATERIAL.MATERIAL_TYPE')
https://laravel.com/docs/7.x/queries#raw-expressions
https://laravel.com/docs/7.x/queries#joins

how to convert SQL query to raw query

SELECT fp.id, fp.name, fp.slug, fp.status, fc.name, fc.slug as category_slug, fp.approved, ff.filepath, fdp.product_id,fdp.type, fdp.sku, fdp.regular_price, fdp.sale_price, fp.created_at, fp.updated_at
FROM `foduu_products` fp
JOIN `foduu_details_product` fdp ON fp.id= fdp.product_id
JOIN `foduu_category_product` fcp ON fp.id = fcp.product_id
JOIN `foduu_filemanager` ff ON fp.filemanager_id = ff.id
JOIN `foduu_categories` fc ON fcp.category_id = fc.id
WHERE fc.slug= "microsoftheadphonesadaptersmotherboardswebcam"
AND fp.approved = 1
AND fp.status = 1
This code should work according to your logic:
$match = ['fc.slug' => 'microsoftheadphonesadaptersmotherboardswebcam', 'fp.approved' => '1', 'fp.status'=>'1'];
$result = DB::table('foduu_products as fd')
->join('foduu_details_product as fdp','fp.id','=','fdp.product_id')
->join(......
.............
->where($match)
->select('fp.id', 'fp.name', ...................)
->get();

Laravel 5 where condition to get pass 30 days worth of records

I have a date column in the instances table with varchar datatype stored as d-m-Y. In my where condition I am trying to fetch records for just past 30 days only.
$backdate = Carbon::parse('-30 days')->toDateString();
$date30DaysBack = Carbon::parse($backdate)->format('d-m-Y');
$adverts = DB::table('adverts')
->where(DB::raw('STR_TO_DATE(instances.date,"%d-%m-%Y")'), '>=',$date30DaysBack)
The full query
$adverts = DB::table('adverts')
->select(DB::raw('(SELECT IF(ext = \'jpeg\', CONCAT(fullpath, \'_1.\', ext), (CONCAT(fullpath,\'.\',ext))) as fullpath FROM advertsstorage where uid_dir = adverts.ad_uid ORDER BY id ASC limit 1)as fullpath, adverts.*, domains.location,instances.date'))
->join('domains','adverts.domain', '=' ,'domains.domain')
->join('advertiser_domains','domains.id', '=' ,'advertiser_domains.domain_id')
->join('advertisers','advertiser_domains.advertiser_id', '=' ,'advertisers.u_id')
->join('instances','adverts.ad_uid','=','instances.ad_uid')
->join('urls','instances.u_id','=','urls.id')
->join('sites','urls.sites_id','=','sites.id')
->where('advertisers.u_id', '=',$advertiserID)
->where(DB::raw('STR_TO_DATE(instances.date,"%d-%m-%Y")'), '>=',Carbon::now()->subDays(30)->format('d-m-Y'))
->orderBy(DB::raw('STR_TO_DATE(instances.date,"%d-%m-%Y")'), 'DESC')
->get();
Did you try DATEDIFF method
$adverts = DB::table('adverts')
->select(DB::raw('(SELECT IF(ext = \'jpeg\', CONCAT(fullpath, \'_1.\', ext), (CONCAT(fullpath,\'.\',ext))) as fullpath FROM advertsstorage where uid_dir = adverts.ad_uid ORDER BY id ASC limit 1)as fullpath, adverts.*, domains.location,instances.date'))
->join('domains','adverts.domain', '=' ,'domains.domain')
->join('advertiser_domains','domains.id', '=' ,'advertiser_domains.domain_id')
->join('advertisers','advertiser_domains.advertiser_id', '=' ,'advertisers.u_id')
->join('instances','adverts.ad_uid','=','instances.ad_uid')
->join('urls','instances.u_id','=','urls.id')
->join('sites','urls.sites_id','=','sites.id')
->where('advertisers.u_id', '=',$advertiserID)
->where(DB::raw('DATEDIFF( now(), STR_TO_DATE(instances.date,"%d-%m-%Y") )'), '<=', 30)
->orderBy(DB::raw('STR_TO_DATE(instances.date,"%d-%m-%Y")'), 'DESC')
->get();
Have you checked out the Carbon docs?
You can use the subtraction modifier for this; Carbon::now()->subDays(30);.
Would look something like this in your code:
$adverts = DB::table('adverts')->where(DB::raw('STR_TO_DATE(instances.date,"%d-%m-%Y")'), '>=', Carbon::now()->subDays(30)->format('d-m-Y'))
Try this.
Carbon has subDays function by which you can get past 30 days data
$date30DaysBack= Carbon::now()->subDays(30)->format('d-m-Y');
$today = Carbon::now()->format('d-m-Y');
$adverts = DB::table('adverts')
->whereBetween(DB::raw('STR_TO_DATE(instances.date,"%d-%m-%Y")'),[$date30DaysBack,$today])->get()

Count from each distinct date, fill in missing dates with zero

I'm trying to create an Eloquent query that gets the total number of posts made each distinct day, and if the date is missing, fill it in with a value of zero.
For example, if my table looks like this:
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2015-01-01 00:00:00 |
| 2 | 2015-01-01 01:53:18 |
| 3 | 2015-01-01 02:41:26 |
| 4 | 2015-01-02 12:51:01 |
| 5 | 2015-01-05 08:24:12 |
+----+---------------------+
This would output:
2015-01-01 : 3
2015-01-02 : 1
2015-01-05 : 1
Notice, however, that the days 03-04 are missing. How can I include these dates, but give them the value 0 such that I end up with an output like:
2015-01-01 : 3
2015-01-02 : 1
2015-01-03 : 0
2015-01-04 : 0
2015-01-05 : 1
Here is my current query:
$posts = Post::select(array(
DB::raw('DATE(`created_at`) as `date`'),
DB::raw('COUNT(*)as `count`')
))
->where('created_at', '>', Carbon::today()->subWeek())
->groupBy('date')
->orderBy('date', 'DESC')
->lists('count', 'date');
Thanks!
In your SQL results you can generate some "fake-data" in your rows, but u can not generate "fake-rows", exept joining to some "fake(temporary)-table".
In your case ll be much easier to apply some logic around sql-result.
Replace your code with this:
$order = 'DESC';
$endDate = Carbon::today();
$startDate = Carbon::today()->subWeek();
$dateInc = ($order == 'DESC') ? -1 : 1;
$dateCycleHolder = clone ($dateInc > 0 ? $startDate : $endDate);
$dateCycleEnd = clone ($dateInc > 0 ? $endDate : $startDate);
$posts = Post::select(array(
DB::raw('DATE(`created_at`) as `date`'),
DB::raw('COUNT(*)as `count`')
))
->where('created_at', '>', $startDate)
->groupBy('date')
->orderBy('date', $order)
->lists('count', 'date');
$postsFinal = new \Illuminate\Database\Eloquent\Collection();
while ($dateCycleHolder->ne($dateCycleEnd)) {
$dateCurr = $dateCycleHolder->format('Y-m-d');
$postsFinal->put($dateCurr, $posts->get($dateCurr, 0));
$dateCycleHolder->addDay($dateInc);
}
$dateCurr = $dateCycleHolder->format('Y-m-d');
$postsFinal->put($dateCurr, $posts->get($dateCurr, 0));
$posts = $postsFinal;
its alittle bit flexible, you can change values of this things:
$order = 'DESC';
$endDate = Carbon::today();
$startDate = Carbon::today()->subWeek();

[Yii][SQL] Do not getting records when join tables to get count of offers

I have following code to can sort by offers(bids and buys):
$clean_criteria = new CDbCriteria;
$clean_criteria->order = 'promoted DESC';
$criteria = new CDbCriteria;
$criteria->order = 'promoted DESC';
$criteria->select = "*, (COUNT(aa.id) + COUNT(ab.id)) as offers";
$criteria->join = ' LEFT JOIN auction_bid aa ON (t.id = aa.auction)';
$criteria->join .= ' LEFT JOIN auction_buy ab ON (t.id = ab.auction)';
I am using pagination and sort:
$item_count = Auction::model()->count($clean_criteria);
$pages = new CPagination($item_count);
$pages->setPageSize(5);
$pages->applyLimit($clean_criteria);
$sort = new CSort('Auction');
$sort->attributes = array('offers'=>array('asc'=>'offers', 'desc'=>'offers DESC'));
$sort->applyOrder($clean_criteria);
But to get offers i must use $crtieria when finding auctions:
$auctions = Auction::model()->findAll($criteria);
On site there is correct pages count, but on every there is one same auction. The problem is query return only one record, but how to fix this?
P.s Maybe i used wrong type of join and auctions which has not offers are not returned?
EDIT:
This code working properly:
$criteria->select = "*, COUNT(abid.id) AS offers1";
$criteria->join = ' LEFT JOIN auction_bid abid ON (t.id = abid.auction)';
$criteria->group = 't.id';
It returns offers1 = 1 for first auction.
Following too :
$criteria->select = "*, COUNT(abuy.id) AS offers2";
$criteria->join = ' LEFT JOIN auction_buy abuy ON (t.id = abuy.auction)';
$criteria->group = 't.id';
It returns offers2 = 4 for first auction
But when i combine it into one query:
$criteria->select = "*, COUNT(abid.id) AS offers1, COUNT(abuy.id) AS offers2";
$criteria->join = ' LEFT JOIN auction_bid abid ON (t.id = abid.auction)';
$criteria->join .= ' LEFT JOIN auction_buy abuy ON (t.id = abuy.auction)';
$criteria->group = 't.id';
It returns offers1 = 4 and offers2 = 4 for first auction.
How to fix it?
Solved:
criteria:
$criteria->select = "*, (COUNT(DISTINCT abid.id) + COUNT(DISTINCT abuy.quantity)) AS `offers`";
$criteria->join = ' LEFT JOIN auction_bid abid ON (t.id = abid.auction)';
$criteria->join .= ' LEFT JOIN auction_buy abuy ON (t.id = abuy.auction)';
$criteria->group = 't.id';
sorting:
$sort = new CSort('Auction');
$sort->attributes = array('offers');
$sort->applyOrder($criteria);
pagination:
$item_count = Auction::model()->count($clean_criteria);
$pages = new CPagination($item_count);
$pages->applyLimit($criteria);
searching:
$auctions = Auction::model()->findAll($criteria);

Resources