How to transform sql query into Query Builder Laravel way? - php

I need to convert this query into Laravel query builder or ORM
SET #start_date = '2020-11-01';
SET #end_date = '2020-11-08';
SET #duration = CONVERT(#end_date, DATE) - CONVERT(#start_date, DATE);
SELECT item_id, days
FROM (
SELECT item_id, sum(end_date - start_date) AS days
FROM schedule WHERE start_date >= #start_date AND end_date <= #end_date
GROUP BY item_id) AS virtual
WHERE days = #duration;
(i use Laravel 8)
i could not find similar example I could analize and try by myself :(
i try this :
$res = DB::table('schedule')
->select('schedule.item_id' , DB::raw("SUM(schedule.end_date - schedule.start_date) as days"))
->where('start_date', '>=', $start_date)
->where('end_date', '<=', $end_date)
->groupBy('item_id')
->where('days', '=', $duration)
->get();
but i get error :
Column not found: 1054 Unknown column 'days' in 'where clause'

ok i know what is wrong
i tried to access 'days' column before it is created with AS
that column will be available after line ->get() is executed.
So I changed order of these 2 lines :
->where('days', '=', $duration)
->get();
to
->get()
->where('days', '=', $duration);
and now works :)

Related

How to select and order an extracted column in PostgreSQL

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"',...

Need equivalent for (non-existent) whereHour command in Laravel

I use the following SQL query to return a set of data (upcoming sessions):
SELECT * FROM availabilities
WHERE
name = "Booked"
and
start_time >= (DATE_ADD(NOW(), INTERVAL 1 DAY))
and
DAY(start_time) >= (DAY(DATE_ADD(NOW(), INTERVAL 1 DAY)))
and
HOUR(start_time) = (HOUR(DATE_ADD(NOW(), INTERVAL 1 DAY)));
This returns the data I need (upcoming sessions 24 hours in advance) but I am struggling to get this into a format that can return the same data in Laravel (using 5.3).
I have this as a start:
$UpcomingSessions = Availability::where('name', '=', 'booked')
->where("start_time",">=", '(DATE_ADD(NOW(), INTERVAL 1 DAY))')
->whereDay("start_time",">=", '(DAY(DATE_ADD(NOW(), INTERVAL 1 DAY)))')
->where("start_time",">=", '(DATE_SUB(NOW(),INTERVAL 1 HOUR))')
->get();
But can't figure out what to do with the hour part as there is no
whereHour
in Laravel.
If I try:
->where("HOUR(start_time)",">=", '(HOUR(DATE_ADD(NOW(), INTERVAL 1 DAY)))')
I get the following message:
Column not found: 1054 Unknown column 'HOUR(start_time)' in 'where clause'
Is there an equivalent command for whereHour that I could use perhaps? Any ideas on how to format the SQL correctly would be great!
Laravel 8.x here.
From the Docs, there is a whereTime() function.
$users = DB::table('users')
->whereTime('created_at', '=', '11:20:45')
->get();
The value given as the second parameter could be any formatted string. So you could, for instance, just narrow it down to 2 whereTime() calls:
$users = DB::table('users')
->whereTime('created_at', '>=', '11:00:00')
->whereTime('created_at', '<', '12:00:00')
->get();
Hey what if you try to use https://laravel.com/docs/5.8/queries#raw-expressions
->where(DB:raw("HOUR(start_time) >= '(HOUR(DATE_ADD(NOW(), INTERVAL 1 DAY)))'))
or
->whereRaw()

Return data ordered by date

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!

Laravel 5.4 - Stats by month

I would like to count all the users who have the state "visible" and "ghost" like this :
public function getStatsUser() {
$data = self::whereIn('state', array('Visible', 'Ghost'))
->count();
return $data;
}
But i would like to have these data each month from the first user, like this :
['Month', 'Data'],
['December 2016', 4000],
['January 2017', 4600],
['February 2017', 11020],
['March 2017', 5400]
And for the date i have a row with "created_at" but not a specific row for the month.
I tried this, but it's not working
$data= self::select(DB::raw('count(*) as monthly_total'), DB::raw('MONTH(created_at) as month'))
->whereIn('state', array('visible', 'Ghost'))
->whereYear('created_at', '=', date('Y'))
->groupBy('month')
->count();
The error :
SQLSTATE[42S22]: Column not found: 1054 Champ 'month' inconnu dans group statement (SQL: select count(*) as aggregate from `oiseau` where `etat_actuel` in (Relaché, En convalescence) and year(`date_signalement`) = 2017 group by `month`)
Thanks for your help !
This should get you started:
self::selectRaw('CONCAT_WS(" ", MONTHNAME(created_at), YEAR(created_at)) as date, COUNT(*) as count')
->whereIn('state', array('visible', 'Ghost'))
->groupBy(DB::raw('YEAR(created_at)', MONTH(created_at)))
->get()
The query will return a Collection of objects with a date and a count.
Probably the most important part is to group by both the year and the month and you can use functions there instead of raw columns.
PS: This will get you Laravel Models from the self class, which they really aren't... so maybe replace the self with DB::table('users') or similar.
You can try like:
$data = self::whereIn('state', array('Visible', 'Ghost'))
->select(DB::raw('count(*) as monthly_total') , DB::raw('MONTH(created_at) month'))
->groupBy('month ')
->get();
Or try Join Query if Month is stored in other Table.

Laravel - select row between start date and end date using eloquent

I want to convert this query into laravel eloquent,
select * from schedule where (now() between start_date and end_date);
I tried using whereBetween, but I got some error.
$schedule = Schedule::whereBetween(Carbon::now(), ['start_date', 'end_date'])->get();
the error looks like this
QueryException in Connection.php line 647:
SQLSTATE[42S22]: Column not found: 1054 Unknown column '2017-06-01 06:17:30' in 'where clause' (SQL: select * from schedule where 2017-06-01 06:17:30 between start_date and end_date)
any idea?
$from = $request->from;
$to = $request->to;
$title="Sales From: ".$from." To: ".$to;
$sales = Sale::whereBetween('created_at', [$from.' 00:00:00',$to.' 23:59:59'])->get();
$schedule = Schedule::where('start_date', '<=', Carbon::now())
->where('end_date', '>=', Carbon::now())
->get();
Or
$schedule = Schedule::whereRaw('(now() between start_date and end_date)')->get();
The whereBetween is used only when you want to find a row where a single column is between 2 values, what you want to do is :
$now = Carbon::now();
$schedule = Schedule::where('start_date', '<=', $now)
->where('end_date', '>=', $now)
->get();
whereBetween should used like this, ->whereBetween('loc_lng', array(-0.24272918701172, -0.24272918701172)) whose first parameter is the column name, and the second is the region.
In you situation you can use ->where('start_date', '<' Carbon::now())->where('end_date', '>' Carbon::now());
You can use whereBetween('date_field',[$from_date, $to_date]) to fetch the data between two dates but it should be in the array format.
$products = Sale::with('products')
->whereBetween('date',[$from_date, $to_date])
->get();
return response()->json($products);
You can also use whereBetween(whereBetween('date_field',[$from_date, $to_date])) with multiple where conditions like:
$products = Sale::with('products')
->whereBetween('date',[$from_date, $to_date])
->where(function ($query) use ($search) {
$query->where('employee_id', 'like', '%'.$search.'%')
->orWhere('employee_name', 'like', '%'.$search.'%');
})
->get();
return response()->json($products);
I hope this will work for you :)

Categories