I have two tables in MySQL. The first table 'table1' records daily data for all the days in a month for specific items. Like this -
id | Item | Date | num_of_items |
---|---|---|---|
1 | Bag | 2021-12-01 | 2 |
2 | Bag | 2021-12-02 | 3 |
3 | Bag | 2021-12-03 | 4 |
4 | Bag | 2021-12-04 | 2 |
5 | Bag | 2021-12-05 | 7 |
6 | Pencil | 2021-12-01 | 2 |
7 | Pencil | 2021-12-02 | 4 |
8 | Pencil | 2021-12-03 | 1 |
9 | Pencil | 2021-12-04 | 5 |
10 | Pencil | 2021-12-05 | 2 |
This goes up to Day 31 if needed for any number of items in the month.
The second table 'table2' contains the rate for the items as it changes during the month and is not constant. It looks like this -
id | Month | Year | Item | Entry Date | Final Date | Rate |
---|---|---|---|---|---|---|
1 | December | 2021 | Bag | 2021-12-01 | 2021-12-02 | 10 |
2 | December | 2021 | Bag | 2021-12-03 | 2021-12-05 | 12 |
3 | December | 2021 | Pencil | 2021-12-01 | 2021-12-03 | 5 |
4 | December | 2021 | Pencil | 2021-12-04 | 2021-12-05 | 3 |
To calculate the total value of Bag's in the month for instance it would be a rate of 10 for the first two days of quantity Day 1 Day 2; 10x6 = 60 plus the rate of 12 for the remaining 3 days - 12x(2 5 1) = 96 for a total of 156 for bags.
I would like to update a 3rd table 'table3' with the total value of each item for that month the moment it is updated with a trigger. The 3rd table would look like this -
id | Item | Month | Year | total |
---|---|---|---|---|
1 | Bag | 12 | 2021 | 156 |
2 | Pencil | 12 | 2021 | 56 |
I know how to manually get the value I want and update table3 with it but have no idea how to automatically do this with a trigger which updates table3 whenever data is inserted or updated into table2.
How do I go about doing something like this?
CodePudding user response:
This is a date-range lookup problem.
Your first step is to make a result set containing the rows of table1
with the appropriate rate
from table2
. The appropriate rate is determined by finding the table2
row with the date range containing the date
of table1
.
Do that with the ON clause of a JOIN. (fiddle here)
SELECT o.id, o.item,
MONTH(o.date) month,
YEAR(o.date) year,
o.num_of_items,
r.rate
FROM table1 o
LEFT JOIN table2 r
ON o.item=r.item
AND o.date >= r.entry_date
AND o.date <= r.final_date;
The last two lines of the query are the trick you need to place table1.date
within the date range. A smart developer will eyeball this result set to ensure it's correct. (That date range stuff can be tricky to get right.)
Then, it's an easy matter to turn the query into a GROUP BY. (fiddle)
SELECT o.item,
MONTH(o.date) month,
YEAR(o.date) year,
SUM(o.num_of_items * r.rate) total
FROM table1 o
LEFT JOIN table2 r
ON o.item = r.item
AND o.date >= r.entry_date
AND o.date <= r.final_date
GROUP BY o.item, MONTH(o.date), YEAR(o.date);
One more thing. You're probably wise to avoid using a trigger and updating a third table with this information. Instead, use a view. That way your data can't be inconsistent. (fiddle)
CREATE OR REPLACE VIEW totals AS
SELECT o.item,
MONTH(o.date) month,
YEAR(o.date) year,
SUM(o.num_of_items * r.rate) total
FROM table1 o
LEFT JOIN table2 r
ON o.item = r.item
AND o.date >= r.entry_date
AND o.date <= r.final_date
GROUP BY o.item, MONTH(o.date), YEAR(o.date);
SELECT * FROM totals;