$teacherStats = DB::table( DB::raw("({$payableContracts->toSql()}) as payable") )
->select('payable.teacher_id')
->selectRaw("CONCAT(first_name, ' ', last_name) as full_name,
SUM(total_direct_benefit + total_indirect_benefit) AS total_benefit,
SUM(teachers_direct_share + teachers_indirect_share) as teachers_share"
)
->selectRaw("DATE('$wageFrom') as wage_from, DATE('$wageTo') as wage_to")
->mergeBindings($payableContracts)
->join('users', 'payable.teacher_id', 'users.id')
->groupBy('payable.teacher_id')
$result = DB::table(DB::raw("({$teacherStats->toSql()}) as stats"))
->leftJoin('teacher_wages', function ($join) use ($wageFrom, $wageTo){
$join->on('stats.teacher_id', '=', 'teacher_wages.teacher_id')
->where('teacher_wages.from', $wageFrom)
->where('teacher_wages.to', $wageTo)
->where('teacher_wages.contracts_type', 'percentage-based');
});
I have $teacherStats as a query and when I get and dd() the result of it, it just works fine. This query is a complicated one but the result is as simple as:
[▼
0 => {#591 ▼
+"teacher_id": 2
+"full_name": "Tom Cruz"
+"total_benefit": "126000"
+"teachers_share": "25200"
+"wage_from": "2020-04-01"
+"wage_to": "2020-04-03"
}
1 => {#594 ▼
+"teacher_id": 5
+"full_name": "John Reno"
+"total_benefit": "296000"
+"teachers_share": "103600"
+"wage_from": "2020-04-01"
+"wage_to": "2020-04-03"
}
]
The problem is with the above $result query which converts $teacherStats to sql as an alias and does a simple join with another table. I get this error:
SQLSTATE[HY093]: Invalid parameter number
without a clue to what parameter and number it refers to.
Related
My query (DB::raw(AVG('pt.progress'))) this part is throwing error at the moment
$query = DB::table('projects as p')
->leftJoin('projects_tasks as pt','pt.project_id', 'p.id')
->select(
'p.id', 'p.project_name', DB::raw(AVG('pt.progress')) //this is where I need the average
);
$query->orderBy($order, $dir);
if ($limit != -1) {
$query->skip($start)->take($limit);
}
$records = $query->get();
Table structure:
projects:
========
id
project_name
...
...
projects_tasks:
===============
id
project_id,
parent, //0 or 1
progress //exmaple value 0.00 to 1.00
How to get the average of progress, where parent_id = 0 and project_id is the same?
The following query does work if I create a function and pass it in a loop, however, I want to optimize it and run it by joining on above query.
$data_row = DB::table('projects_tasks')
->select(DB::raw('(SUM(progress)*100)/count(progress) as project_progress'))
->where(['project_id' => $project_id, 'parent' => 0])
->get();
Seems that you have a syntax error on your query, the problem is in here DB::raw(AVG('pt.progress')).
Since you're using a raw query, the parameter there should be a string, so you must enclose that in quotes / double qoute.
$query = DB::table('projects as p')
->leftJoin('projects_tasks as pt','pt.project_id', 'p.id')
->select(
'p.id', 'p.project_name', DB::raw("AVG('pt.progress')")
);
$query->orderBy($order, $dir);
if ($limit != -1) {
$query->skip($start)->take($limit);
}
$records = $query->get();
I want to get count from 'user' table with 'plan_validity' is null or more than today's date. both condition need to check for same column with user_id and status = 1.
$currentUser = User::where('user_id', $card_details->user_id)
->where('status', 1)
->where(function (Builder $query) {
return $query
->whereDate('plan_validity', '>=', Carbon::now())
->orWhere('plan_validity', null);
})->count();
giving error
[2021-11-23 10:40:31] production.ERROR: Argument 1 passed to App\Http\Controllers\ProfileController::App\Http\Controllers\{closure}() must be an instance of App\Http\Controllers\Builder, instance of Illuminate\Database\Eloquent\Builder given, called in /home/hellovcard/public_html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php on line 237 {"userId":17,"exception":"[object] (TypeError(code: 0): Argument 1 passed to App\\Http\\Controllers\\ProfileController::App\\Http\\Controllers\\{closure}() must be an instance of App\\Http\\Controllers\\Builder, instance of Illuminate\\Database\\Eloquent\\Builder given, called in /home/hellovcard/public_html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php on line 237 at /home/hellovcard/public_html/app/Http/Controllers/ProfileController.php:34)
how to modify above mentioned query?
this is output I need to get
enter image description here
You are not combining your "where" clauses properly. With the "orWhere" at the end, it essentially ignores all the conditions (ie. which user it relates to) of the preceding where clauses, so adds to the results any row where plan_validity is null. So after you query by user ID and status, you then need to combine the remainder of the query into a logical group like so :
$user = Users::where('user_id', $card_details->user_id)
->where('status', 1)
->where(function (Builder $query) {
return $query
->whereDate('plan_validity', '>=', Carbon::now())
->orWhere('plan_validity', null);
})
->get();
I have the following query:
$products = Product::leftJoin(DB::Raw('(SELECT imageable_id, MIN(created_at) as min_created_at
FROM images WHERE imageable_type = "App\\\Product"
GROUP BY imageable_id) AS subquery'), function($join) {
$join->on('subquery.imageable_id', '=', 'products.id');
})
->leftJoin('images', function ($join) {
$join->on('images.imageable_id', '=', 'subquery.imageable_id')
->where('images.created_at', '=', 'subquery.min_created_at');})
->select('products.*', 'images.file_path')
->paginate(5);
When I die and dump the query log, the above gets translated as follows:
"query" => """
select `products`.*, `images`.`file_path` from `products`
left join (SELECT imageable_id, MIN(created_at) as min_created_at
FROM images WHERE imageable_type = "App\\Product"
GROUP BY imageable_id) AS subquery on `subquery`.`imageable_id` = `products`.`id`
left join `images` on `images`.`imageable_id` = `subquery`.`imageable_id` and `images`.`created_at` = ?
limit 5 offset 0
"""
"bindings" => array:1 [
0 => "subquery.min_created_at"
]
Which looks correct, though I'm unsure why a binding has been added for subquery.min_created_at
Now when I execute the above the query in laravel images.file_path is always null when clearly I know there are related images. When I test the above query by pasting it and running directly in MySQL command line I get the expected results i.e. for products which have images, file_path for image is not null. The only difference when I run in MySQL command line is that I'm not doing any binding for subquery.min_created_at - I simply replaced the ? with subquery.min_created_at
Any ideas why the query is behaving this way. If I remove the second left join it works correctly but then I can't select the first created image to load e.g doing the following give me the file_path:
$products = Product::leftJoin(DB::Raw('(SELECT imageable_id, file_path
FROM images WHERE imageable_type = "App\\\Product"
GROUP BY imageable_id) AS subquery'), function($join) {
$join->on('subquery.imageable_id', '=', 'products.id');
})
->select('products.*', 'subquery.file_path')
->paginate(5);
Ideally I want to get my original query working in - any help appreciated.
You are using ->where() for your second join condition:
->where('images.created_at', '=', 'subquery.min_created_at')
This generates
and `images`.`created_at` = ?
which the binding is for.
Instead you should use ->on();
$join->on('images.imageable_id', '=', 'subquery.imageable_id')
->on('images.created_at', '=', 'subquery.min_created_at');
In sql, I have this query, It is working perfectly and order by given array in "order BY Field". But in cakephp it is not working.
SELECT * FROM users
WHERE users.Id IN (3,7,2,13)
ORDER BY FIELD(users.Id ,3,7,2,13)
I get the users in following order. which is perfect
user _id
3
7
2
13
Cakephp 3
$unique_user_id_list = (3,7,2,13);
$id_list = '3','7','2','13'; This is string.
$users = $this->Users->find('all',[
'contain' => [],
'conditions'=>['Id IN' => $unique_user_id_list],
'order BY FIELD'=>['Users.Id'=>$id_list]
]);
In this query, I get user in following order
user_id
2
3
7
13
I tried both following ways but no one work. Only "order" clause gives error while other one "order by field" gives no error but does not work as expected.
'order'=>['Users.Id'=>$id_list]
'order BY FIELD'=>['Users.Id'=>$id_list]
Any idea how to write above sql query in cakephp 3 to get it work.
Answer for this question
In short words 'order' => "FIELD(id, '2', '3', '7', '13')"
In detail first use loop to convert array in string.
$id_list;
foreach ($unique_user_id_list as $key => $value) {
if($check == 1){
$id_list = 'FIELD ( Id'.',' . "'". $value. "'";
$check =2;
}
else{
$id_list = $id_list . "," . "'". $value. "'";
}
}
$id_list = $id_list . ")";
above loop will generate "FIELD(id, '2', '3', '7', '13')"
Full query how I used it is given below.
$users = $this->Users->find('all',[
'contain' => [],
'conditions'=>['Id IN' => $unique_user_id_list],
'order'=> $id_list
]);
Try formatting the order statement as follows
->order(['users.Id'=>'ASC']);
I have:
$buyingNet = DB::table('parts_enquiries_buying AS PEB')
->select(DB::raw('SUM((PEB.quantity*PEB.net)/IF(ISNULL(currencyRate), rate, currencyRate)) AS total'))
->join('currencies_rates AS CR', function ($q) {
$q->on('CR.id', '=', 'PEB.currencyId')
//->where(DB::raw('YEAR(CR.date)'), '=', date('Y'))
->where(DB::raw('MONTH(CR.date)'), '=', date('m'));
})
->leftJoin('jobs', 'jobs.enquiryId', '=', 'PEB.enquiryId')
->leftJoin('invoices_out AS IO', 'IO.jobId', '=', 'jobs.id')
->where('PEB.enquiryId', $enquiryId)
->first()->total;
If I uncomment the where that matches the year I get null returned, but all the rows that should be there are there.
Is my syntax correct? It should translate as:
... YEAR(CR.date) = ? AND MONTH(CR.date) =? ...
I believe the issue here is that Query builder doesn't understand your DB::raw statement within the ->where clause.
You should do as folllows:
->whereRaw("YEAR(CR.date) = '". date('Y')."'")
->whereRaw("MONTH(CR.date) = '". date('n')."'")
for the month clause you need to use n instead of m since MySQL MONTH returns a single digit for months below 10.