Finding sum through eager loading - php

I've a table schema as follows:
+----+---------------+------------+--------+
| id | crowd_fund_id | email | amount |
+----+---------------+------------+--------+
| 1 | 11 | jj#xx.com | 200 |
| 2 | 11 | sd#ff.com | 250 |
| 3 | 12 | jj#xx.com | 150 |
| 4 | 12 | abc#cc.com | 230 |
+----+---------------+------------+--------+
And a Entries table:
+----+---------+----------+------+
| id | user_id | crowd_id | name |
+----+---------+----------+------+
| 1 | 6 | 11 | Abc |
| 2 | 6 | 12 | Xyc |
| 3 | 8 | 18 | ijn |
+----+---------+----------+------+
In the Backer's Model
public function entry()
{
return $this->belongsTo('App\Entries', 'crowd_fund_id', 'crowd_id');
}
and in the Controller I've called:
$var = Backers::with('entry')->where('email', $user->email)->get();
This works fine. Now I wanted to get the sum also through the eager loading.
That means I need to call something like
Backers::with('entry')->with('sum')->where('email', $user->email)->get();
The sum will calculate the total of all the amount where crowd_fund_id is equal to the raw where email = $user->email.
That means when I call
Backers::with('entry')->with('sum')->where('email', $user->email)->get();
I should be getting :
1 raw for the backer's details with crowd_fund_id
1 raw for the corresponding entry where crowd_fund_id = crowd_id
1 sum of all amount where crowd_fund_id = crowd_fund_id from the backer's details.
How can I get this?

Could you try something along these lines (in your Backers model):
public function backersSum()
{
return $this->hasOne('App\Backer')
->selectRaw('crowd_fund_id, sum(amount) as aggregate')
->groupBy('crowd_fund_id');
}
Doing it this way allows you to eager load it like any relationship. Then you could do something like this to access it:
public function getBackersSumAttribute()
{
if ( ! $this->relationLoaded('backersSum'))
$this->load('backersSum');
$related = $this->getRelation('backersSum');
return ($related) ? (int) $related->aggregate : 0;
}

Related

Dynamically create MySQL table columns

I have the following MySQL table which is structured like that:
| id | bonus0 |
Now I want to add the following data set:
| id | bonus0 | bonus1 | bonus2 | bonus3 |
| 10 | 4582 | 2552 | 8945 | 7564 |
As you can see the columns bonus1 - bonus3 arenĀ“t created yet.
How would a php script/ query look like which checks if enough columns are already available and if not which will create the missing ones with consecutive numbers at the end of the word "bonus"?
So in the example the columns bonus1 - bonus3 would be created automatically by the script.
In reality (I mean a normalized relational database) you should have 3 tables. Lets call them people, bonuses and bonus_to_person
people looks like:
+-----------------+------------+
| person_id | name |
+_________________+____________+
| 1 | john |
+-----------------+------------+
| 2 | frank |
+-----------------+------------+
bonuses Looks like
+----------------+--------------+
| bonus_id | amount |
+________________+______________+
| 1 | 1000 |
+----------------+--------------+
| 2 | 1150 |
+----------------+--------------+
| 3 | 1200 |
+----------------+--------------+
| 4 | 900 |
+----------------+--------------+
| 5 | 150 |
+----------------+--------------+
| 6 | 200 |
+----------------+--------------+
bonus_to_person Looks like
+----------------+-----------------+
| bonus_id | person_id |
+________________+_________________+
| 1 | 1 |
+----------------+-----------------+
| 2 | 2 |
+----------------+-----------------+
| 3 | 2 |
+----------------+-----------------+
| 4 | 1 |
+----------------+-----------------+
| 5 | 1 |
+----------------+-----------------+
| 6 | 1 |
+----------------+-----------------+
This way, any ONE person can have unlimited bonuses simply by INSERTING into bonuses with the amount, and INSERTING into bonus_to_person with the bonus_id and person_id
The retrieval of this data would look like
SELECT a.name, c.amount from people a
LEFT JOIN bonus_to_people b
ON a.person_id = b.person_id
LEFT JOIN bonuses c
ON c.bonus_id = b.bonus_id
WHERE a.person.id = 1;
Your result from something like this would look like
+------------+----+-------+
| name | amount |
+____________+____________+
| john | 1000 |
+------------+------------+
| john | 900 |
+------------+------------+
| john | 150 |
+------------+------------+
| john | 200 |
+------------+------------+
You should be using this normalized approach for any database that will continue growing -- Growing "deeper" than "wider" is better in your case ..
// Get existing columns of the table
// $queryResult = run SQL query using PDO/mysqli/your favorite thing: SHOW COLUMNS FROM `table`
// Specify wanted columns
$search = ['bonus0', 'bonus1', 'bonus2', 'bonus3'];
// Get just the field names from the resultset
$fields = array_column($queryResult, 'Field');
// Find what's missing
$missing = array_diff($search, $fields);
// Add missing columns to the table
foreach ($missing as $field) {
// Run SQL query: ALTER TABLE `table` ADD COLUMN $field INT
}

Symfony 4 #Gedmo\SoftDeleteable() for form with collection type form

I have problem with soft delete item with form collection in Symfony framework
I want to add and remove items in relation with Symfony form collection, If I remove item from collection this item must soft deleted from relation records
with below image you can imagine relations
This is my form collections in Symfony forms
Main form
+
|
ProductType+
| |
| |
| PackagesType+
| |
| |
| PackageProductsType
|
|
+
Package products add and removed with JS in frontend based on Symfony example for form collections
my problem is when I remove completely from package_product with activating orphanRemoval=true in annotation of entity every thing work well but record removed completely and I want record soft deleted based on my propose, But when I change below function in Package Entity
public function removePackageProduct(PackageProduct $packageProduct): self
{
if ($this->packageProducts->contains($packageProduct)) {
$this->packageProducts->removeElement($packageProduct);
// set the owning side to null (unless already changed)
if ($packageProduct->getPackage() === $this) {
$packageProduct->setPackage(null);
}
}
return $this;
}
always in top function I get last record in packageProducts and when I remove this line $packageProduct->setPackage(null); to disable loosing data in record and replace it with $packageProduct->setDeletedAt(new \Datetime()); to set deleted item, In saved records removed record delete from database and a new record added filled with last record data and deletedAt datetime.
For example:
PackageProduct records before delete first item:
+----+------------+------------+--------+-----------+
| ID | Product_id | package_id | amount | deletedAt |
+----+------------+------------+--------+-----------+
| 1 | 10 | 1 | 3 | |
| 2 | 11 | 1 | 4 | |
| 3 | 12 | 1 | 5 | |
+----+------------+------------+--------+-----------+
PackageProduct records after delete first item:
+----+------------+------------+--------+-----------+
| ID | Product_id | package_id | amount | deletedAt |
+----+------------+------------+--------+-----------+
| 2 | 11 | 1 | 4 | |
| 3 | 12 | 1 | 5 | |
| 4 | 12 | 1 | 5 |2020-1-20..|
+----+------------+------------+--------+-----------+
But I expected PackageProduct records after delete first item:
+----+------------+------------+--------+-----------+
| ID | Product_id | package_id | amount | deletedAt |
+----+------------+------------+--------+-----------+
| 1 | 10 | 1 | 3 |2020-1-20..|
| 2 | 11 | 1 | 4 | |
| 3 | 12 | 1 | 5 | |
+----+------------+------------+--------+-----------+
How can fix this to get expected result?

How to fetch record from three table in laravel eloquent

I have four tables
jobposts:
id | user_id | cat_id | job_title
1 | 1 | 1 | job 1
2 | 1 | 2 | job 2
3 | 2 | 3 | job 3
4 | 1 | 3 | job 4
categorymasters:
id | category_name
1 | cat1
2 | cat2
3 | cat3
4 | cat4
lastsubcategoryselectedbycompanies:
id | jobposts_id | lastsubcategorymasters_id
1 | 1 | 1
2 | 1 | 2
3 | 2 | 3
4 | 1 | 3
lastsubcategorymasters:
id | LastSubCategoryName
1 | lastsubcat1
2 | lastsubcat2
3 | lastsubcat3
4 | lastsubcat4
jobposts have unique rows.
lastsubcategoryselectedbycompanies is a mapping of jobposts and lastsubcategorymasters.
Now assume some user is logged in with their credentials (EX: take user_id 1 in jobposts). Now I need to show LastSubCategoryName in a comma separated list from the lastsubcategorymasters table, grouped by the jobposts, lastsubcategoryselectedbycompanies and lastsubcategorymasters tables.
allpostedjob.blade.php is:
#foreach($jobposteddetails as $jobposteddetail)
<tr>
<td>{{ $jobposteddetail->job_title }}</td>
</tr>
#endforeach
cotroller is:
public function index()
{
$user = Auth::user();
$jobposteddetails = jobpost::with('categorymaster')->where('user_id', '=', $user->id)->get();
return view('jobprovider.allpostedjob', compact('user','jobposteddetails'));
}
jobpost.php model is:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class jobpost extends Model
{
function categorymaster()
{
return $this->belongsTo(categorymaster::class, 'cat_id');
}
}
It is working proper.
But I also need to show LastSubCategoryName grouped by the tables jobposts, lastsubcategoryselectedbycompanies and lastsubcategorymasters.
function lastsubcategory()
{
return $this->belongsTo(lastsubcategoryselectedbycompanies::class);
}
It is not working. How can I fetch my result?
I am not very skilled at applying complex queries with eloquent, I prefer to use DB query builder with the join method
https://laravel.com/docs/5.8/queries

$this->db->group_by() and adding the quantity

I have this in my receipt UI(Note: This is only from one user):
Item_Name | Quantity | Price | Total
Panty | 2 | 50 | 100
Bra | 1 | 35 | 35
Panty | 2 | 50 | 100
As you can see the user gets the Panty TWICE!
I want my UI to be looking like this:
Item_Name | Quantity | Price | Total
Panty | 4 | 50 | 100
Bra | 1 | 35 | 35
As you can see the Panty's that the user buys groups together, but in my query instead of Panty having 4 Quantity it still has 2
Here is my Code:
public function getClientReservation($name){
$this->db->select('*');
$this->db->from('tbl_item_availed');
$this->db->join('tbl_items','tbl_items.Item_ID = tbl_item_availed.Item_ID');
$this->db->join('user_account','user_account.Account_no = tbl_item_availed.Account_no');
$this->db->where('Username',$name);
$this->db->where('isReserve',1);
$this->db->where('Active',1);
$this->db->group_by('tbl_items.Item_Name');
$query = $this->db->get();
return $query->result();
}
Please help!
This is the table tbl_item_availed by the way:
Item_availed_id | Item_ID | Quantity | Account_no
1 | 1 | 2 | 5
2 | 2 | 1 | 5
3 | 1 | 2 | 5
table tbl_items:
Item_ID | Price | Item_Name
1 | 100 | Panty
2 | 35 | Bra
table user_account:
Account_no | Firstname | Lastname
1 | LeBron | James
2 | Dwyane | Wade
3 | Wilt | Chamberlain
4 | Michael | Jordan
5 | Charles | Barkley
Try this.
public function getClientReservation($name){
$this->db->select('tbl_items.`Item_Name`, SUM(tbl_item_availed.`Quantity`) AS quantity, tbl_items.`Price`, (tbl_items.`Price`*(SUM(tbl_item_availed.`Quantity`))) AS total');
$this->db->from('tbl_item_availed');
$this->db->join('tbl_items','tbl_items.Item_ID = tbl_item_availed.Item_ID');
$this->db->join('user_account','user_account.Account_no = tbl_item_availed.Account_no');
$this->db->where('Username',$name);
$this->db->where('isReserve',1);
$this->db->where('Active',1);
//$this->db->group_by('tbl_items.Item_Name');//do not use this line unless item name is unique
//group by item id
$this->db->group_by('tbl_items.Item_ID');
$query = $this->db->get();
return $query->result();
}
Also use GROUP BY for Item_ID (assuming it is unique), not Item_Name unless it is unique.
Side note:
Moreover, use Account_no instead of username in WHERE clause. If you want to modify it, just replace this line
$this->db->where('Username',$name);
with
$this->db->where('Account_no',$account_no);

Query mysql when reach row then stop? show the queue number

I am doing a script want to calculate how many row record before an user record when t1.status is 1.
My table is t1, and the data as below:
+------+---------+------------+----------+----------+
| ID | name | desc | status | time |
+------+---------+------------+----------+----------+
| 1 | ABB | | 1 | 0325 |
| 2 | CCD | | 1 | 0236 |
| 3 | EEF | | 1 | 0325 |
| 4 | GGG | | 1 | 0000 |
| 5 | HIJ | | 2 | 1234 |
| 6 | KKK | | 1 | 5151 |
+---------------------------------------------------+
I was thinking about the query is something like (query row where status = 1 AND stop when reach $userid)
I would like to output to show user (Let's say username is GGG) as:
$userid = 'GGG';
then my output will be
<table><tr><td>Queue: GGG You came in 4 place, in front of you still got 3 person in queue, please be patient</td></tr></table>
How to I do the right query to get the number 4 and 3 ?
Thank you.
You can try something like this hope it helps :-
SELECT count(*) as COUNT FROM t1 WHERE id < (SELECT id FROM t1 WHERE userid = $userid)

Categories