SQL request with GROUP BY and SUM in Eloquent - sql

I just want make a simple sql request in my laravel application.
I'm not very comfortable with Eloquent aha.
This is the SQL request I want to make with eloquent :
select user_id, project_id, sum(hours)
FROM time_entries
WHERE spent_on BETWEEN '2018-04-10' AND '2018-12-10'
GROUP BY user_id, project_id
I've been trying something like :
TimeEntries::whereBetween('spent_on', [($request->input('debut')), ($request->input('fin'))])->groupBy('user_id')->sum('hours');
(but you can see it's hopeless)

Use selectRaw().
TimeEntries::whereBetween('spent_on', [($request->input('debut')), ($request->input('fin'))])->groupBy(['user_id', 'project_id'])->selectRaw('user_id , project_id, sum(hours) as sum')->get();

You can use the selectRaw function of Eloquent,
like this:
TimeEntries::selectRaw('user_id, project_id, sum(hours)')
->whereBetween(
'spent_on',
[ ($request->input('debut')), ($request->input('fin')) ]
)
->groupBy('user_id', 'project_id');
But be aware that not to binding variables in the selectRaw string parameter, it might cause SQL injection problem since it by-pass the escaping check

Below query will work:
$query = TimeEntries::query();
$query->selectRaw('user_id', 'project_id', sum(hours))
->whereRaw("spent_on >= '2018-04-10' and spent_on <= '2018-12-10'")
->groupBy('user_id')
->groupBy('project_id');
$result = $query->get();

Model->select(DB::raw('user_id, project_id,
SUM(hours)')->whereBetween...

Related

Laravel subquery query

I want to use subquery in query as select. But this code doesnt work.
$listed_waiting_approach = DB::table('be_medical_insurance_for_foreigners')
->join('be_product','be_product.id','=','be_medical_insurance_for_foreigners.product_id')
->join('be_status','be_status.id','=','be_medical_insurance_for_foreigners.payment_status_id')
->where('be_medical_insurance_for_foreigners.is_approved','=',false)
->where('be_medical_insurance_for_foreigners.is_active','=',true)
->where('be_medical_insurance_for_foreigners.payment_status_id','=',$payment_status_id1)
->where('be_medical_insurance_for_foreigners.order_status_id','=',$order_status_id1)
->select('be_medical_insurance_for_foreigners.*','be_product.name as productname','be_medical_insurance_for_foreigners.is_approved as approve','be_status.code as statuscode','**(SELECT code FROM be_status WHERE id=$payment_status_id1 ) as paymentname**')
->get();
You can use a DB::raw combine with a DB::select. That is something like
DB::select( DB::raw( " ... ") )
You can also use selectRaw:
DB::table('be_medical_insurance_for_foreigners')
->selectRaw("be_medical_insurance_for_foreigners.*, be_product.name as productname, be_medical_insurance_for_foreigners.is_approved as approve, be_status.code as statuscode, (SELECT code FROM be_status WHERE id={$payment_status_id1}) as paymentname")
->get();

cannot group with eloquent with PostreSQL

Here's my Eloquent query:
$visits = Visit::orderBy('date', 'desc')->groupBy('user_id')->get(['date', 'user_id']);
But posgreSQL is refusing the query, telling me:
SQLSTATE[42803]: Grouping error: 7 ERROR: column "visits.date" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: select "date", "user_id" from "visits" group by...
the same stuff works on MySQL when I disable ONLY_FULLY_GROUP_BY
what can I do to make it work? It would be great if I didn't have to edit configs, just the code.
This selects the latest date for each user_id:
$sub = Visit::select('user_id', DB::raw('max("date") "date"'))->groupBy('user_id');
$sql = '(' . $sub->toSql() . ') as "sub"';
$visits = Visit::join(DB::raw($sql), function($join) {
$join->on('visits.user_id', 'sub.user_id')
->on('visits.date', 'sub.date');
})->orderBy('visits.date', 'desc')->get(['visits.date', 'visits.user_id']);
If there are multiple visits for a user_id and date combination, the query returns all of them. Removing the duplicates is possible, but makes the query more complex.
It's easier to remove them afterwards:
$visits = $visits->unique('user_id');
Using postgre sql you could use distinct on user_id and order your date column to pick latest date per user_id, In laravel you could raw expression
$visits = Visit::select(DB::raw('distinct on (user_id)'), 'date')
->orderBy('date', 'desc')
->get();
Demo

Use SQL query in Laravel

this is my sql Query:
SELECT DISTINCT batch_job_instance.JOB_NAME, MAX(batch_job_execution.CREATE_TIME) AS CREATED_TIME, batch_job_execution.END_TIME, batch_job_execution.STATUS FROM `batch_job_execution` INNER JOIN batch_job_instance ON batch_job_execution.JOB_INSTANCE_ID = batch_job_instance.JOB_INSTANCE_ID WHERE batch_job_execution.CREATE_TIME LIKE '%2016-12-05%' GROUP BY batch_job_instance.JOB_INSTANCE_ID ORDER BY MAX(batch_job_execution.CREATE_TIME) DESC
my Question, how i use that query in laravel? i am new in laravel, can someone help me? i need this for my project Thanks :)
You can run this SQL query as ot is if you had problem in converting in laravel format.
You can use :
DB::select(DB::RAW(your_sql_query)):
Hope this will help.
You can create a function within your model and query the data using the bellow format
public static function getJobs()
{
$jobs = DB::table('batch_job_execution')
->select(
DB::raw('
DISTINCT batch_job_instance.JOB_NAME,
MAX(batch_job_execution.CREATE_TIME) AS CREATED_TIME,
batch_job_execution.END_TIME,
batch_job_execution.STATUS
'
)
)
->join('batch_job_instance', 'batch_job_execution.JOB_INSTANCE_ID', '=', 'batch_job_instance.JOB_INSTANCE_ID')
->where('batch_job_execution', 'LIKE', '%2016-12-05%')
->groupBy('batch_job_instance.JOB_INSTANCE_ID')
->orderBy(DB::raw('MAX(batch_job_execution.CREATE_TIME)'),'DESC')
->get();
// ->toSql();
return $jobs;
}

How to count the number of rows with a date from a certain year in CodeIgniter?

I have the following query.
$query = $this->db->query('SELECT COUNT(*) FROM iplog.persons WHERE begin_date LIKE '2014%'');
I need to count the number of columns with a begin_date in the year 2014.
When I run this script I'm getting an error:
Parse error: syntax error, unexpected '2014' (T_LNUMBER) in C:\xampp\htdocs\iPlog2\application\controllers\stat.php on line 12
I was trying to change my CI script to
$query = $this->db->query('SELECT COUNT(*) FROM iplog.persons WHERE begin_date LIKE "2014%"');
but it caused an error.
You mean, count ROWS:
So for that, just count the number of rows you have based on a condition:
$year = '2014'
$this->db->from('iplog');
$this->db->like('begin_date', $year);
$query = $this->db->get();
$rowcount = $query->num_rows();
First, you have a simple typo regarding the use of single quotes. Your complete sql string should be double quoted so that your value-quoting can be single quoted.
Second, you are using inappropriate query logic. When you want to make a comparison on a DATE or DATETIME type column, you should NEVER be using LIKE. There are specific MYSQL functions dedicated to handling these types. In your case, you should be using YEAR() to isolate the year component of your begin_date values.
Resource: https://www.w3resource.com/mysql/date-and-time-functions/mysql-year-function.php
You could write the raw query like this: (COUNT(*) and COUNT(1) are equivalent)
$count = $this->db
->query("SELECT COUNT(1) FROM persons WHERE YEAR(begin_date) = 2014")
->row()
->COUNT;
Or if you want to employ Codeigniter methods to build the query:
$count = $this->db
->where("YEAR(begin_date) = 2014")
->count_all_results("persons");
You could return all of the values in all of the rows that qualify, but that would mean asking the database for values that you have no intention of using -- this is not best practice. I do not recommend the following:
$count = $this->db
->get_where('persons', 'YEAR(begin_date) = 2014')
->num_rows();
For this reason, you should not be generating a fully populated result set then calling num_rows() or count() when you have no intention of using the values in the result set.
Replace quotes like this :
$query = $this->db->query("SELECT COUNT(*) FROM iplog.persons WHERE begin_date LIKE '2014%'");
Double quote your entire query, then simple quote your LIKE criteria.

Select distinct value count laravel

I have an orders table where there is a status column.
I am trying to get the count of each status like this :
$pending = Order::where('status','=','pending')->count();
$active = Order::where('status','=','active')->count();
But this is not efficient as am having to make one call for each status type.
How can I reduce number of queries ?
To make an SQL request:
SELECT count(DISTINCT `status_id`) FROM `dbname`.orders WHERE `user_id` = '2';
In Laravel you can try the following:
$user->orders()->distinct()->count(["status_id"]);
You could try
$orders = Order::select(DB::raw('count(*) as order_count, status'))
->groupBy('status')
->get();
here is the way you write ->
$users= DB::table('table_name')->distinct()->get(['column_name']);
$users_count = $users->count();