MySQL how to update aggregated table (based on another table) automatically? [duplicate] - mysql

This question already has answers here:
How do I create a view in MySQL? [closed]
(2 answers)
Closed last month.
I have a table (table1) in a MySQL database with data similar to this:
Category
total_sold
revenue
profit
fruit
32
200
150
veggies
12
50
23
chips
23
170
110
fruit
43
300
180
chips
5
25
15
New data is inserted into the table regularly through a python script using sqlalchemy (appends csv files to the mysql table using Pandas).
I want to create an aggregated table (table2) based on category using a query, and I want the aggregation to update whenever I add new records to the table1.
For example after executing the query:
CREATE TABLE table2 AS
SELECT Category, AVG(total_sold) avg_sold, AVG(revenue) avg_revenue, AVG(profit) avg_profit
FROM table1
GROUP BY 1
I get table2 as:
Category
avg_sold
avg_revenue
avg_profit
fruit
37.5
250
165
veggies
12
50
23
chips
14
97.5
62.5
Now if I insert several new records to table1, how can I make table2 update automatically? (recalculate all aggregations based on all table1 records including the newly added ones)
I read about creating a trigger, but I'm not sure how to execute it or if it would work in a case like this.
I Would appreciate any help.

MySQL does not support "materialized views". You have to do the aggregation yourself. Build a separate Summary Table and keep it updated. A simple IODKU is one way to do that maintenance; the link discusses other, such as a nightly batch update of the day's data.

Related

Nested sort in SELECT followed by Conditional INSERT based upon results of SELECT inquiry

I have been struggling with the following for some time.
The server I am using has MySQL ver 5.7 installed.
The issue:
I wish to take recorded tank level readings from one table, find the difference between the last two records for a particular tank, and multiply this by a factor to get a quantity used.
The extracted quantity, if it is +ve, else 0 , then to be inserted into another table for further use.
The Quant value extracted may be +ve or -ve as tanks fill and empty. I only require the used quantity -ie falling level.
The two following tables are used:
Table 'tf_rdgs' sample;
value 1 is content height.
id
location
value1
reading_time
1
18
1500
2
18
1340
3
9
1600
4
18
1200
5
9
1400
6
18
1765
yyyy
7
18
1642
xxxx
Table 'flow' example
id
location
Quant
reading_time
1
18
5634
dd-mm: HH-mm
2
18
0
dd-mm: HH-mm
3
18
123
current time
I do not require to go back over history and am only interested in the latest level readings as a new level reading is inserted.
I can get the following to work with a table of only one location.
INSERT INTO flow (location, Quant)
SELECT t1.location, (t2.value1 - t1.value1) AS Quant
FROM tf_rdgs t1 cross join tf_rdgs t2 on t1.reading_time > t2.reading_time
ORDER BY t2.reading_time DESC limit 1
It is not particularly efficient but works and gives the following return from the above table.
location
Quant
18
123
for a table with mixed locations including a WHERE t1.location = ... statement does not work.
The problems i am struggling with are
How to nest the initial sorting by location for the subsequent inquiry of difference between the last two tank level readings.
A singular location search is ok rather than all tanks.
A Conditional INSERT to insert the 'Quant' value only if it is +ve or else insert a 0 if it is -ve (ie filling)
I have tried many permutations on these without success.
Once the above has been achieved it needs to run on a conditional trigger - based upon location of inserted data - in the tf_rdgs table activated upon each new reading inserted from the sensors on a particular tank.
I can achieve the above with the exception of the conditional insert if each tank had a dedicated table but unfortunately I cant go there due existing data structure and usage.
Any direction or assitance on parts or whole of this much appreciated.

MYSQL Group in one table and multiply with numbers from another table

I have two tables as below:
goods_in:
in_id|pid|in_num|in_date
1 1001 10 2020-06-28
2 1002 20 2020-06-28
3 1001 20 2020-05-25
......
stock:
stock_id|pid|num|price
1 1001 10 5
2 1002 15 6
3 1003 20 7
...
The "goods_in" table stores the records that all goods come into warehouse, the pid in this table is the same as in table "stock" which is the product ref code. There will be multiple records for each product in "goods_in" table.
The "stock" table stores all the SKU we are holding and the current stock level as well as the product cost.
What I'm trying to do is:
Group by pid AND date (Year+Month) from "goods_in" so I get sub-total number of goods booked-in in each month.
Multiple sub-total with stock.price.
Get total amount of above, something like SUMPRODUCT in excel.
Exports to html table or excel.
I've tried several answers from SO with GROUP BY/ROLLUP/JOIN, and apparently I haven't made it right as expected. I can make this simple if I just add a cost column to the "goods_in" table but that would make it untidy.
I'm still on my learning curves with MYSQL, forgive me if this looks simple to you guys.
Thanks.
Ken
Hard to know for sure what you want, but it sounds something like this:
select
pid,
year(in_date) as year,
month(in_date) as month,
sum(goods_in.in_num * stock.price)
from goods_in
join stock using (pid)
group by pid, year, month
For exporting to html or excel, you are best off asking a separate question.

T-SQL query procedure-insert

I am wondering if any of you would be able to help me. I am trying to loop through table 1 (which has duplicate values of the plant codes) and based on the unique plant codes, create a new record for the two other tables. For each unique Plant code I want to create a new row in the other two tables and regarding the non unique PtypeID I link any one of the PTypeID's for all inserts it doesnt matter which I choose and for the rest of the fields like name etc. I would like to set those myself, I am just stuck on the logic of how to insert based on looping through a certain table and adding to another. So here is the data:
Table 1
PlantCode PlantID PTypeID
MEX 1 10
USA 2 11
USA 2 12
AUS 3 13
CHL 4 14
Table 2
PTypeID PtypeName PRID
123 Supplier 1
23 General 2
45 Customer 3
90 Broker 4
90 Broker 5
Table 3
PCreatedDate PRID PRName
2005-03-21 14:44:27.157 1 Classification
2005-03-29 00:00:00.000 2 Follow Up
2005-04-13 09:27:17.720 3 Step 1
2005-04-13 10:31:37.680 4 Step 2
2005-04-13 10:32:17.663 5 General Process
Any help at all would be greatly appreciated
I'm unclear on what relationship there is between Table 1 and either of the other two, so this is going to be a bit general.
First, there are two options and both require a select statement to get the unique values of PlantCode out of table1, along with one of the PTypeId's associated with it, so let's do that:
select PlantCode, min(PTypeId)
from table1
group by PlantCode;
This gets the lowest valued PTypeId associated with the PlantCode. You could use max(PTypeId) instead which gets the highest value if you wanted: for 'USA' min will give you 11 and max will give you 12.
Having selected that data you can either write some code (C#, C++, java, whatever) to read through the results row by row and insert new data into table2 and table3. I'm not going to show that, but I'll show how the do it using pure SQL.
insert into table2 (PTypeId, PTypeName, PRID)
select PTypeId, 'YourChoiceOfName', 24 -- set PRID to 24 for all
from
(
select PlantCode, min(PTypeId) as PTypeId
from table1
group by PlantCode
) x;
and follow that with a similar insert.... select... for table3.
Hope that helps.

SQL query to identify max value in an subset of records to be used as boundary condition for Batch Job partitioning

I have around 2 million records in the database and I want to us the concept of partitions in one of my batch jobs. In order to do this I need to first identify the boundary records of the partition. Can anyone help out to identify boundry values using SQL query. To illustrate consider i have student records as follows
STUDENT_ID STUDENT_NAME
1 JACK
2 SPARROW
3 JONNY
4 WALKER
5 SKY
6 DANNY
Now if i want to create 2 partitions by boundary condition of first partition will be STUDENT_ID between 1 to 3 and STUDENT_ID between 4 to 6. consider similar situation incase student_id is a string or random id. How to identify the bounday condition. Currently I am thinking of first querying all the records in the database and then partitioning them in the java code. But if I have 2 million records this is highly not recommended what should i do in this condition?
You can use limit command in mySql as follow:
SELECT...
LIMIT y OFFSET x

Update a field in one table on row insertion in another table

I have the following two tables:
1) Transactions Table
TID ID
---- --
1212 21
1313 31
1414 21
1515 44
1616 21
1717 31
2) Products Table
PID Count
--- -----
21 7
31 8
44 9
(Original counts value was 10)
I would like to achieve this: when ever I add a transaction in the transaction table, I want to be able to check if the product I'm trying to sell have sufficient quantity in the product table (1 or more) and if it does, allow the addition in the transaction table and decrease the count of the product in the product table.
I tried to do this by going to Table->After Add/After update.. etc. but with no help. Also didn't find resources on the web. I'm using Access 2013.
You actually need two (2) data macros on the [Transactions] table: a Before Change data macro to see if the transaction can be entered ...
... and an After Insert data macro to update the [Products] table: