Get the count of a specific column with join query in Laravel - php

I have 2 tables, products and stocks. Each product has a stock record foreign key product_id in the stocks table. Each stock record has a quantity column.
Fields in the stocks table look like,
id | product_id | color_id | quantity
In brief: 1 product can have many stock records. I'm trying to get the product and its total count in the quantity column of stock records. Imagine product A (product id is 1) has 3 stock records in the stocks table like this,
id | product_id | color_id | quantity
1 | 1 | 3 | 10
2 | 1 | 4 | 20
3 | 1 | 2 | 40
Here for product A the total of quantity column in the stocks table is 10 + 20 + 40 = 70. I'm expecting to return this 70 and the product record.
Here is my code. I have no idea how to get that,
return DB::table('products')
->join('stocks', 'products.id', '=', 'stocks.product_id')
->paginate(5);

If your joins are correct use sum() with groupBy() clause
->select(DB::raw("SUM(stocks.quantity) as stocks_quantity"))
->groupBy('stocks.product_id') # or ->groupBy('products.id')
DB::table('products')
->join('stocks', 'products.id', '=', 'stocks.product_id')
->select(DB::raw("SUM(stocks.quantity) as stocks_quantity"))
->groupBy('products.id') #or groupBy('stocks.product_id')
->paginate(5);
Edit 01
DB::table('products')
->join('stocks', 'products.id', '=', 'stocks.product_id')
->select('products.*')
->selectRaw("SUM(stocks.quantity) as stocks_quantity")
->groupBy('stocks.product_id')
->get(5);
Edit 02
add 'products.id' in select
DB::table('products')
->leftjoin('stocks', 'products.id', '=', 'stocks.product_id')
->select('products.id','products.*')
->selectRaw("SUM(stocks.quantity) as stocks_quantity")
->groupBy('products.id')
->get(5);

Related

Multiple category id wise show product in laravel 9

I am trying to building ecoommerce system using laravel 9. Everything goes fine but Suddenly I got one issue. I want to show product based on category id but my product table category id store multiple. Bellow I am showing my table structure:
Product Table:
|---ID---|---Name---|---Cat_id---|---Status--|
| 1 | T-shirts | 1,2, | active |
| 2 | Pants | 4,3, | active |
| 3 | Sweaters | 5,2, | active |
Category Table
|---ID---|---Name---|
| 1 | General |
| 2 | News |
| 3 | Festival |
| 4 | Category |
Controller
public function category($slug)
{
//
$cat = Category::where('slug', $slug)->first();
$products = Product::whereIn('cat_id', [$cat->id])->where('status', 'active')->orderby('id', 'asc')->paginate('12');
return view('frontend/Catproducts', compact('products', 'cat'));
}
Now I want when I am click on "NEWS" category I want to see two product. How can I fix it
As #aynber said in the comments, best solution is to normalize the database, so you have a setup like this:
Categories table:
id
name
Products table:
id
name
status
Product_categories table:
id
product_id
category_id
With a belongsToMany relationship from Product to Category(and back), your query should look something like:
$categoryIdArray = [2];
Product
::whereHas('category', function($query) use($categoryIdArray) {
$query->whereIn('id', $categoryIdArray);
})
->get();
It is still possible with your current setup though, while a little hacky:
$cat = Category
::where('slug', $slug)
->first();
$catId = $cat->id;
$products = Product
::where(function($where) {
$where->where('cat_id', 'like', "$catId,%")//Look for first cat in col, don't forget trailing comma
->orWhere('cat_id', 'like', "%,$catId,%")//Look for appended cat between commas
})
->where('status', 'active')
->orderby('id', 'asc')
->paginate('12');
This will work on small scale, but because we are using like, mysql needs to check ALL records, and cannot optimize the query. That's the reason why normalization is important :)

Getting result from array of Ids in Laravel

I've a following attendance table:
id | grade_id | subject_id | date | students
1 | 2 | 6 | 2020-05-05 | [3,6,8,11,17,21,20,19]
I want to fetch all rows with name of all students from array of Ids.
What I've tried is:
$result[] = Attendance::where('date', '=', $day)
->with('grades', 'subjects')
->join('students', function($join) {
$join->on('students.id', '=', 'attendances.id')
->where('students.id', '=', 'attendances.students');
})->get();
But couldn't get result. Please help me!
It is not a proper table structure.Will be better if you make another table like
id | attendance_id | student_id
1 | 1 | 3
1 | 1 | 6
And make its relation in model with attendance and student table.This way table will be normalized and will be easy to handle relationship.

Using sum in eloquent laravel when have quantity and price

I have problem with my projects e-commerce
in,in this problem i have 2 tables.
Table Products
ID | Name_products | Price
P1 | Product A | 2000
P2 | Product B | 5000
P3 | Product C | 7500
Table User Carts
ID | User_id | Product_id | Quantity
C1 | User1 | P1 | 2
C2 | User1 | P2 | 1
I have using this query eloquent :
$totalPricec = MyCart::where('user_id', Auth::user()->id)
->select('products.nama_produk', 'products.id as product_id','products.price''my_carts.quantity','my_carts.id as id')
->join('products', 'products.id', '=', 'my_carts.product_id')
->sum('price');
but i got price is 7000 (product A = 2000 + product B = 5000)
should be 9000 (product A = 2000 * 2 + product B = 5000 * 1)
how i can get the total price actually?
I using this query
$totalPricec = MyCart::where('user_id', Auth::user()->id)
->select('products.nama_produk', 'products.id as product_id','products.price''my_carts.quantity','my_carts.id as id')
->join('products', 'products.id', '=', 'my_carts.product_id')
->sum(DB::raw('products.price * my_carts.quantity'));
and thats work :)
thank you for user #user3532758

How can I calculate total price of an invoice?

I have two three tables:
// invoices
+----+----------------+
| id | invoice_code |
+----+----------------+
| 1 | d09823r230r4 |
| 2 | 34tf354f45tf |
+----+----------------+
// commodities
+----+-------------+------------+--------+
| id | invoice_id | product_id | number |
+----+-------------+------------+--------+
| 1 | 1 | 1 | 2 |
| 2 | 1 | 3 | 4 |
+----+-------------+------------+--------+
-- number columns is the number of each ordered product in the invoice
// products
// invoices
+----+-----------+---------+
| id | name | price |
+----+-----------+---------+
| 1 | SFX-300 | 15000 |
| 2 | GB32-b10 | 2000 |
| 3 | SVX-m30 | 1200 |
+----+-----------+---------+
All I need to do is calculating the total price of an invoice. Here is the formula to calculate the total price for invoice x:
$total_invoice_price = 0;
foreach( $invoice_x->commodities as $commodity){
$total_invoice_price += ( $commodity.number * <products.price> )
}
echo $total_invoice_price;
The problem is about getting <products.price>. It needs one more join to products table. Any idea how can I do that using Laravel relationships ?
If you just need the total price, this could be done in pure sql with aggregate statements and joins over the three tables.
SELECT invoice.invoice_code, SUM(product.price * commodities.number)
FROM invoice
JOIN commodities ON invoice.id = commodities.invoice_id
JOIN product ON product.id = commodities.product_id
GROUP BY invoice.id
To save the query, you should do eager loading using "with()" the model you wish to join.
I'm not sure how you named your model and how well it linked to each other.
Let's assume that it've been done in the conventional way.
Here is the script.
$total_invoice_price = $invoice_x->commodities
->with('products')
->get()
->map(function ($commodity) {
return $commodity->number * $commodity->product->price;
})
->sum();
What I've done is after getting the products joined with each commodity. I do the get() to have the commodities collection. The from the collection, we do map on each commodity and return the number and price of product. Then we multiply and return as the sum of each commodity record. After that we sum all the totals to the grand total and get your result.
I wrote the code without testing, so try to adjust it to your code.
Please check below Query
$invoices_total = DB::table('invoices')
->join('products', 'invoices.id', '=', 'commodities.invoice_id')
->join('commodities', 'products.id', '=', 'commodities.product_id')
->sum('products.price * commodities.number')
->groupBy('invoices.id')
->get();

Calculate sum using Laravel Query Builder by applying groupBy on Table1.id but without soft deleted rows on Table2?

I want to get all the purchases and their sums and also I don't want to add the amount if payments.deleted_at is not null.
Here are the tables
purchases
id | name
1 | Gamerzone Book
2 | Recipe Book
3 | EngineX Book
payments
id | purchase_id | amount | deleted_at
1 1 100 2015-06-12 11:00:00
2 2 50 NULL
2 2 10 NULL
Code
$query = DB::table('purchases')
->select(['purchases.*',
DB::raw("IFNULL(sum(payments.amount),0) as total")
])
->leftJoin('payments','payments.purchase_id','=','purchases.id')
->whereNull('payments.deleted_at')
->groupBy('purchases.id')->get();
When I run the code below the 1st result is not included.
Result
id | name | total
2 | Recipe Book 60
3 | EngineX Book 0
I know why It is not included but the problem is if I remove whereNull('payments.deleted_at') that particular row in payments
will also add to the sum.How should I solve this ??
Expected Result
id | name | total
1 | Gamerzone Book 0
2 | Recipe Book 60
3 | EngineX Book 0
In this case your join condition should looks like this:
ON (payments.booking_id = purchases.id AND payments.deleted_at IS NOT NULL)
And it is not about WHERE (according to your SELECT).
You should use join-closure like this:
$query = DB::table('purchases')
->select(['purchases.*', DB::raw("IFNULL(sum(payments.amount),0) as total")])
->leftJoin('payments', function($join) {
$join->on('payments.booking_id', '=', 'purchases.id');
$join->on('payments.deleted_at', 'IS', DB::raw('NOT NULL'));
})
->groupBy('purchases.id')->get();
Just replace
->leftJoin('payments','payments.booking_id','=','purchases.id')
with
->leftJoin('payments', function($join) {
$join->on('payments.booking_id', '=', 'purchases.id');
$join->on('payments.deleted_at', 'IS', DB::raw('NOT NULL'));
})
and remove this:
->whereNull('payments.deleted_at')
it should help.

Categories