Laravel - Unknown column 'subscription_date' in 'group statement' - laravel

I want to perform aggregate function and achieve a specific result that group by date, removing time from datetime.
Whenever I group by created_at the error will not be there but it will group by datetime and the result will not be accurate.
I have this query:
Your query seems correct but I think you forgot to retrieve the as keyword,
$revenuereports = DB::table('cloudsubscriptions as c')
->select(
'c.service_name',
DB::raw('COUNT(*) as total_users'),
DB::raw('SUM(c.amount) as total_amount'),
DB::raw('DATE(c.created_at)as subscription_date') // you forgot as here
)
->groupBy('subscription_date')
->orderByRaw('c.created_at DESC');
$render=[];
if(isset($request->start_date) && isset($request->end_date))
{
$revenuereports=$revenuereports->whereBetween('created_at',[$request->start_date,$request->end_date]);
$render['start_date']=$request->start_date;
$render['end_date']=$request->end_date;
}elseif(isset($request->start_date))
{
$revenuereports=$revenuereports->where('created_at',$request->start_date);
$render['start_date']=$request->start_date;
}
if(isset($request->service_name))
{
$revenuereports=$revenuereports->where('service_name','like','%'.$request->service_name.'%');
$render['service_name']=$request->service_name;
}
//dd($revenuedetails->toSql());
$revenuereports= $revenuereports->orderBy('created_at','DESC');
$revenuereports= $revenuereports->paginate(15);
$revenuereports= $revenuereports->appends($render);
$data['revenuereports'] = $revenuereports;
return view('report.revenueReport',$data);
I expect to have a result to filter by subscription_date (without time)
"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'subscription_date' in 'group statement' (SQL: select count(*) as aggregate from cloudsubscriptions as c where created_at between 2019-01-01 and 2019-06-30 group by subscription_date) "
How do I resolve it please?

Do you have the field in database?
Then you should forgot to add as just before subscription_date
$revenuereports = DB::table('cloudsubscriptions as c')
->select('c.service_name', DB::raw('COUNT(*) as total_users'), DB::raw('SUM(c.amount) as total_amount'),DB::raw('DATE(c.created_at) as subscription_date'))
->groupBy('subscription_date')
->orderByRaw('c.created_at DESC')
->get();
BTW, i dont think you need a table alias for this query.
$revenuereports = DB::table('cloudsubscriptions')
->select('service_name', DB::raw('COUNT(*) as total_users'), DB::raw('SUM(amount) as total_amount'),DB::raw('DATE(created_at) as subscription_date'))
->groupBy('subscription_date')
->orderBy('created_at', 'desc')
->get();
You can change your mysql strict->false and try.
You will find it on, config/database.php > connections > strict (default it is true, just change it to false.)

Your query seems correct but I think you forgot to retrieve the as keyword,
$revenuereports = DB::table('cloudsubscriptions as c')
->select(
'c.service_name',
DB::raw('COUNT(*) as total_users'),
DB::raw('SUM(c.amount) as total_amount'),
DB::raw('DATE(c.created_at)as subscription_date') // you forgot as here
)
->groupBy('subscription_date')
->orderByRaw('c.created_at DESC')
->get();

Related

Laravel 8 - How I do where clause in table added with join

Hi I want to know how can i do this query in Laravel 8 , I tried adding the join clause but not work as expected, i need join clause? Or maybe there is another form to do it. I search others examples but i donĀ“t see anythat help me. The query is the next:
DB::table('escandallo_p as esc')
->select("esc.material", "esc.referencia", "esc.ancho", "esc.proveedor", "esc.punto",
"esc.precio", "esc.consumo", "esc.veces", "esc.001", "esc.002", "esc.003", "esc.004",
"esc.005", "esc.006", "esc.007", "esc.008", "esc.009", "esc.010", "esc.011", "esc.um", "esc.merma", "esc.importe", "esc.tipo", "esc.xtalla", "esc.fase",
DB::raw("(select anulado from prototipos_p as p where p.prototipo = '".$scandal[0]->prototipo."' and p.tipo = 'c' and p.referencia = esc.referencia )"),
// ignore
//original query "(select anulado from prototipos_p as p where p.prototipo = ",$request->prototipo," and p.tipo = 'c' and p.referencia = esc.referencia ) as 'anulado'",
// "(select clase from prototipos_p as p where p.prototipo = ",$request->prototipo," and p.tipo = 'c' and p.referencia = esc.referencia ) as 'clase'")
//Converted query ->select('pro.anulado')->where('pro.prototipo', $request->prototipo)
// ->where("p.prototipo", "=", $request->prototipo)
->where("esc.id_escandallo", "=", $request->id_escandallo)
->where("esc.id_version", "=", $request->version)
->orderBy("id","asc")
->get();
!!!! I need to pass the esc.referencia to the sub select query
The second select is the conversion of the select inside "" ( i know this is wrong is only for explain it).
Thank you in advance for any suggestion.
Best regards
EDIT: I can solve my problem with DB::raw, but if anyone know others methos are welcome!
You need to pass callback to the join query to add the extra query to the laravel's join method,
Example from Laravel Doc:
DB::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')
->where('contacts.user_id', '>', 5);
})
->get();
It is explained in Laravel's doc, Advanced Join Clauses
There is Subquery support too Subquery Joins,
Eg:
$latestPosts = DB::table('posts')
->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))
->where('is_published', true)
->groupBy('user_id');
$users = DB::table('users')
->joinSub($latestPosts, 'latest_posts', function ($join) {
$join->on('users.id', '=', 'latest_posts.user_id');
})
->get();
These two might help you to achieve what you are trying
After test joins, joinSub, whereIn and other forms of doing this, I solved my problem using the DB::raw():
DB::table('escandallo_p as esc')
->select('parameters',....,
DB::raw("(SELECT column //(ONLY ONE)
FROM table
WHERE column = '".$parameter."' ...) AS nombre"),
)
->where('column', "=", $parameter)
->orderBy("id","asc")
->get();

How to get created column using SelectRaw and use it inside whereBetween

I've got a laravel eloquent query which uses selectRaw and whereBetween:
$offset = '+8:00';
$d["records"] = data_entries::select("*")
->selectRaw("CONVERT_TZ (testTime, '+0:00', '{$offset}') as convertedTime")
->whereBetween("testTime", $filters['duration'])
->where('data_entries.patientID_FK', '=', $patient['patientID'])
->leftjoin('additional_notes', 'ID', '=', 'additional_notes.entryID_FK')
->get();
So this query works and I can get convertedTime data. But I want to use convertedTime instead of testTime in whereBetween like this:
$d["records"] = data_entries::select("*")
->selectRaw("CONVERT_TZ (testTime, '+0:00', '{$offset}') as convertedTime")
->whereBetween("convertedTime", $filters['duration'])
->where('data_entries.patientID_FK', '=', $patient['patientID'])
->leftjoin('additional_notes', 'ID', '=', 'additional_notes.entryID_FK')
->get();
but I got error saying unknown column 'convertedTime'. Is there a way to get the date that was converted based on timezone inside the whereBetween?
You cannot refer to an alias defined in the select clause in the where clause at the same level of the query. But it just so happens that MySQL has overloaded the HAVING operator such that it can be used in place of WHERE, with the added feature that it can also refer to aliases. Consider the following version:
$d["records"] = data_entries::select("*")
->selectRaw("CONVERT_TZ (testTime, '+0:00', '{$offset}') AS convertedTime")
->where('data_entries.patientID_FK', '=', $patient['patientID'])
->leftjoin('additional_notes', 'ID', '=', 'additional_notes.entryID_FK')
->havingRaw("convertedTime >= ? AND convertedTime <= ?", $filters['duration'])
->get();

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

db::raw adding is null in query

I am trying to use laravel query builder like:-
$users = DB::table('baid_collection')
->select(DB::raw('sum(total) as total_collect,collection_limit_c'))
->join('users_cstm', 'baid_collections.assigned_user_id', '=', 'users_cstm.id_c')
->where(DB::raw("assigned_user_id = '$userId' and DATE(date_entered)=CURDATE()"))
->groupBy('assigned_user_id')
->get();
This query should be like
select sum(total) as total_collect,collection_limit_c from `baid_collections` inner join `users_cstm` on `baid_collections`.`assigned_user_id` = `users_cstm`.`id_c` where assigned_user_id = '15426608-3ea5-f299-7a80-601bd06be2d9' and DATE(date_entered)=CURDATE() group by `assigned_user_id`
But last run query showing me
select sum(total) as total_collect,collection_limit_c from `baid_collection` inner join `users_cstm` on `baid_collections`.`assigned_user_id` = `users_cstm`.`id_c` where assigned_user_id = '15426608-3ea5-f299-7a80-601bd06be2d9' and DATE(date_entered)=CURDATE() is null group by `assigned_user_id`
In query is null giving problem i dont want is null in query
Use whereRaw instead of where like
$users = DB::table('baid_collections')
->select(DB::raw('sum(total) as total_collect,collection_limit_c'))
->join('users_cstm', 'baid_collections.assigned_user_id', '=', 'users_cstm.id_c')
->whereRaw("assigned_user_id = '{$userId}' and DATE(date_entered)=CURDATE()")
->groupBy('assigned_user_id')
->get();
It's creating a problem due to where needs atleast two parameters and you are just passing one parameter
Check this if it helps, write whereDate instead of add date in raw query.
if you are not using Carbon, you can also use php date("Y-m-d"), method to get date
DB::table('baid_collection')
->select(DB::raw('sum(total) as total_collect,collection_limit_c'))
->join('users_cstm', 'baid_collections.assigned_user_id', '=', 'users_cstm.id_c')
->where(DB::raw("assigned_user_id = '$userId'"))
->whereDate("date_entered", "=", Carbon::now()->toDateString())
->groupBy('assigned_user_id')->get();
You can try this
$users = DB::table('baid_collection')
->select(DB::raw('sum(total) as total_collect,collection_limit_c'))
->join('users_cstm', 'baid_collections.assigned_user_id', '=', 'users_cstm.id_c')
->where(DB::raw("assigned_user_id = '$userId' and DATE(date_entered) = '".date('Y-m-d')."'"))
->groupBy('assigned_user_id')
->get();

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