I have 3 tables ( customers
, invoices
, invoice_items
).
A customer can have multiple invoices and an invoice can have multiple items.
This is my current schema:
customers
id
name
timestamps
invoices
id
customer_id
timestamps
invoice_items
id
invoice_id
price
timestamps
Note: timestamps are created_at
and updated_at
fields. No need to worry.
as you can see, I am not storing the total amount of an invoice in the invoices table. I let the front-end calculate it.
Now, my client has 1000+ customers and they want to show all customers in the homepage along with the total sum of all invoices they have.
ID | Customer name | Total Invoice (sum of all invoices)
Right now I am using Laravel, so my query looks like this:
$customers = Customer::with('invoices.items')->get();
What's the best way to do this? Performance wise?
Should I just store the total amount of each invoice in the invoices table to avoid querying the items and calculate the sum? Something like:
invoices
id
customer_id
total
timestamps
Imagine a customer having thousand invoices and each invoice has multiple items. The query will be very slow and I have to calculate every thing in the front-end.
Also, when an invoice has been made, it can't be changed. So the total for an invoice is static.
It looks good apart from the timestamps. Can you not just use one timestamp column in your invoices table?
Why do you need the same column in all 3 tables?
Also, I'm sure you can calculate total in your php script. You don't need to store the total that you can calculate through a count() in php.
Ofcourse, when you add a total
column on invoice
table then you should get a boost in the performance, as you will not have to go through all the invoice_items
and add them up. This is good if you need to add items to the invoice
only at once and do not need to be updated later. This way, you will need to add the total while generating the invoice at once.
Adding total
column in invoice table will be definitely good for performance and it will also help fetch result through eloquent. However, if performance is not something important here, we can do it without it. Your SQL query should be like (might need little adjustment)
SELECT c.*, i.*, sum(ii. price) as total_invoice_price
FROM customers c
INNER JOIN invoices i on i.customer_id = c.id
INNER JOIN invoice_items ii on ii.invoice_id = i.id
GROUP BY i.id
Once you have expected result through SQL, you can run it using DB::table
in laravel.
This is classic case of WORM (Write Once Read Many).
Lets look into pros and cons of both the approaches:
Case 1: Not storing the total in invoices table
Case 2: Storing the total in invoice table
Now if you look into the cons of both the approaches, case 2 is obviously better because extra storage can be bought easily but performance can't be even if you increase RAM and CPU upto some extent.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.