I have a function that returns the count of sales each day. The problem with this approach is that I want the data to be stored by date but I am getting them in the following order:
01-Dec
02-Dec
03-Dec
03-Nov
04-Nov
05-Nov
etc.
I understand why that happens but I am not sure how to solve it. I can replace subMonth(1) with startofmonth which woul partially solve my problem but this is not what I want. I instead want to return the last 30 days ordered.
return DB::table('sales')
->select(\DB::RAW('DATE_FORMAT(created_at, "%d-%M") as date'), \DB::raw('COUNT(*) as count'))
->where('created_at', '>=', Carbon::now()->subMonth(1))
->orderBy('date')
->groupBy('date')
->get(['date', 'count'])
->keyBy('date')
->transform(function ($data) {
return $data->count;
});
I also tried orderBy('created_at') but it gives me the error below and I'd like to avoid changing the sql mode.
Syntax error or access violation: 1055 Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'x.sales.created_at' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
EDIT:
As requested, this the sql query of the return statement
select DATE_FORMAT(created_at, "%d-%M") as date, COUNT(*) as count from `sales` where `created_at` >= ? group by `date` order by `date` asc
i don't have much idea about your framework query syntax. but you can take one more column DATE_FORMAT(created_at, "%Y%m%d") AS order_column and apply order, and group by on column "order_column" and use column "data" while display data.
select DATE_FORMAT(created_at, "%Y%m%d") AS order_column, DATE_FORMAT(created_at, "%d-%M") as date, COUNT(*) as count from `sales` where `created_at` >= ? group by `order_column` order by `order_column` asc
return DB::table('sales')
->select(\DB::RAW('DATE_FORMAT(created_at, "%Y%m%d") AS order_column'),\DB::RAW('DATE_FORMAT(created_at, "%d-%M") as date'), \DB::raw('COUNT(*) as count'))
->where('created_at', '>=', Carbon::now()->subMonth(1))
->orderBy('order_column')
->groupBy('order_column')
->get(['date', 'count'])
->keyBy('date')
->transform(function ($data) {
return $data->count;
});
If you make this in 2 steps does it work?
Step1 in which you create date column:
$step1 = DB::table('sales') ->select(\DB::RAW('DATE_FORMAT(created_at, "%d-%M") as date')))
->where('created_at', '>=', Carbon::now()->subMonth(1))
->orderBy('date')
->get(['date', 'count'])
and after that you make the agregation:
$step2 = $step1->select('date'), \DB::raw('COUNT(date) as count'))
->groupBy('date') ->get(['date', 'count']) ->keyBy('date')
Hope it helps!
Related
I am using Laravel Framework 6.16.0.
I have the following sql query:
SELECT DISTINCT
`companies`.*
FROM
`companies`
LEFT JOIN `trx` ON `trx`.`companies_id` = `companies`.`id`
WHERE
`trx`.`transaction_date` >= 2020-11-12 AND companies.symbol NOT IN (SELECT DISTINCT
companies.symbol
FROM
`companies`
LEFT JOIN articles a ON a.companies_id = companies.id
WHERE
a.created_at >= 2020-11-12
ORDER BY
created_at
DESC)
ORDER BY
transaction_date
DESC
I have created the following eloquent query:
DB::connection('mysql_prod')->table('companies')->select('companies.symbol')
->leftJoin('trx', 'trx.companies_id', '=', 'companies.id')
->where('trx.transaction_date', '>=', Carbon::today()->subDays(1)->startOfDay())
->orderBy('transaction_date', 'desc')
->distinct()
->get('symbol');
However, I am not sure how to pack the in my eloquent query to get all the symbol back that should be excluded.
I highly appreciate your replies!
You should try something like this:
$date = Carbon::today()->subDays(1)->startOfDay();
DB::connection('mysql_prod')->table('companies')->select('companies.symbol')
->leftJoin('trx', 'trx.companies_id', '=', 'companies.id')
->where('trx.transaction_date', '>=', $date)
->whereNotIn('companies.symbol', function ($q) use ($date) => {
$q->select('companies.symbol')
->from('companies')
->leftJoin('articles', 'articles.companies_id', 'companies.id')
->where('articles.created_at', '>', $date)
->distinct()
->get()
})
->orderBy('transaction_date', 'desc')
->distinct()
->get();
It will provide a similar query as you mentioned.
Reference from here.
Also, you can read how to write sub Query from Laravel docs.
Check this one more good answer for that what you need.
I have a query builder to select all users created in the last 12 months
$range = \Carbon\Carbon::now()->subYears(1);
$countUser = DB::table('users')
->select(DB::raw('month(created_at) as getMonth'),
DB::raw('year(created_at) as getYear'),
DB::raw('COUNT(*) as value'))
->where('created_at', '>=', $range)
->groupBy('getMonth','getYear')
->orderBy('getMonth', 'ASC')
->get();
This query works fine with MySQL, However, when I deploy it on Heroku which runs with PostgreSQL database it returns an error
column "getMonth" does not exist LINE 1: ...end date)", "extract(year from created_at)" order by "getMonth"... ^ (SQL: select extract(month from created_at) as getMonth, extract(year from created_at) as getYear, COUNT(*) as value from "users" where "created_at" >= 2019-10-01 03:16:43 group by "extract(month from created_at)", "extract(year from created_at)" order by "getMonth" asc)
I tried to search and figured out that postgest has a different statement to get month and year in created_at column and I change my code to this and it also returns the error not found column getMonth for the GroupBy()
$range = \Carbon\Carbon::now()->subYears(1);
$countUser = DB::table('users')
->select(DB::raw('extract(month from created_at) as getMonth'),
DB::raw('extract(year from created_at) as getYear'),
DB::raw('COUNT(*) as value'))
->where('created_at', '>=', $range)
->groupBy('getMonth','getYear')
->orderBy('getMonth', 'ASC')
->get();
Does PostgreSQL have any naming rules to set a name for a selected column or does it has any way to solve my problem?
Thanks for reading!
If you use mixed-case aliases in postgresql, they have to be quoted. Use get_month instead of getMonth, or use AS "getMonth" and groupBy('"getMonth"',...
I'm trying to conver this SQL query to Laravel query.
SELECT count(*) FROM (SELECT order_id FROM table1 WHERE app_process='7' AND ( service_type='lite' OR ((end_time-".time().")/86400)>'0') ) a INNER JOIN (SELECT order_id FROM table2 WHERE process='1' AND amount>'0' GROUP BY order_id) b ON a.order_id=b.order_id
I almost success(?) to converting but I don't know how to convert the time part.
end_time-".time().")/86400
what I converted
Db::table('table1 as A')
->select('A.order_id')
->where('A.app_process', '=', '7')
->where('A.service_type', '=', 'lite')
->orWhere('A.end_time', '>', '0') <== problem here!!
->join(Db::raw('(select order_id from table2 where process = 1 and amount > 0 group by order_id) B'), 'B.order_id', '=', 'A.order_id')
->count();
Could someone help me to solve the time part?
As far as I understand the query, it just checks if end_time is in the future. So you can just do the following:
->orWhere('A.end_time', '>', now())
now() is a Laravel helper that returns the current datetime.
I finally found out the right query. It turns out the problem was not only just 'time()' but also the wrong converted query.
I post this maybe help someone.
Db::table('table1 as A')
->leftJoin('table2 as B', 'A.order_id', '=', 'B.order_id')
->where('A.app_process', '=', '7')
->where(function($query){
$query->where('A.service_type', '=', 'lite')->orWhere('A.end_time', '>', time());
})
->where('B.process', '=', '1')
->where('B.amount', '>', '0')
->distinct()
->count('A.order_id');
try this I think it helps you
Db::table('table1 as A')
->select('A.order_id')
->where([['A.app_process', '=', '7'],['A.service_type', '=', 'lite']])
->orWhere('A.end_time', '>', now())
->join(Db::raw('(select order_id from table2 where process = 1 and amount > 0 group by order_id) B'), 'B.order_id', '=', 'A.order_id')
->count();
I have a table named shopping_apps, and that table has different entries on different dates. I want to have all records but group all the records on a date basis (not the time part). Suppose I have 20 entries on date1, 12 entries on date2. I want to have only two values extracted from the database: date1 and date2. The controller is below, and Shopping_app is my model name.
<?php
// Use substr() to retrieve date part 10 chars in length.
$shoppingApp = Shopping_app::orderBy('created_at', 'DESC')
->groupBy(substr('created_at', 0, 10))
->get();
ERROR:
SQLSTATE[42000]: Syntax error or access violation: 1055
'laravelpro4.shopping_apps.id' isn't in GROUP BY (SQL: select * from
shopping_apps group by created_at order by created_at desc)
$shoppingApp = Shopping_app::where('created_at', '>=', \Carbon\Carbon::now->subMonth())
->groupBy(DB::raw('Date(created_at)'))
->orderBy('created_at', 'DESC')->get();
try this maybe it will help you
So with the help of #manish I get the correct answer (what I was trying to get)
Error solved by
Adding false
In config\database.php --> "mysql" array
Set 'strict' => false to disable all.
Final code :
$shoppingApp = Shopping_app::where('created_at', '>=', \Carbon\Carbon::now()->subMonth())
->groupBy(DB::raw('Date(created_at)'))
->orderBy('created_at', 'DESC')->get();
I'd like to get the difference between two dates on two tables. The uploads.published_at compared to the completed_guides.created_at
I keep getting an error which says:
SQLSTATE[42000]: Syntax error or access violation: 1582 Incorrect parameter count in the call to native function 'datediff' (SQL: select users.*,completed_guides.created_at as completed_at,uploads.published_at,datediff(HOUR, published_at, completed_at) from `users` inner join `uploads` on `users`.`id` = `uploads`.`user_id` inner join `completed_guides` on `uploads`.`id` = `completed_guides`.`upload_id` where `completed_guides`.`upload_id` = 2839 limit 10)
Here is my code. Any help would be appreciated.
$select = [
'users.*',
'completed_guides.created_at as completed_at',
'uploads.published_at',
'datediff(HOUR, published_at, completed_at) as date_diff'
];
return User::select(DB::raw(join(',', $select)))
->join('uploads', 'users.id', '=', 'uploads.user_id')
->join('completed_guides', 'uploads.id', '=', 'completed_guides.upload_id')
->where('completed_guides.upload_id', $this->id)
->take(10)
->get();
You can use Laravel Query Builder's whereRaw() like this:
return User::select(DB::raw(join(',', $select)))
->join('uploads', 'users.id', '=', 'uploads.user_id')
->join('completed_guides', 'uploads.id', '=', 'completed_guides.upload_id')
->where('completed_guides.upload_id', $this->id)
->whereRaw('datediff(uploads.published_at, completed_guides.completed_at) as date_diff')
->take(10)
->get();
To set the format of date you can use SQL method - date_format(date, format) like this:
->select(DB::raw("DATE_FORMAT(date_diff, '%b %d %Y %h:%i %p') as formatted_date_diff"));
See more about SQL Date Format
Hope this helps!
The one with units, is timestampdiff, not datediff.
timestampdiff(HOUR, published_at, completed_at) as date_diff