Get Min and Max after summation in MySql - mysql

I have a dataset as follows,
Table_Date Description Amount
4/17/2022 A 10
4/17/2022 B 45
4/17/2022 C 34
4/17/2022 D 23
4/17/2022 E 76
4/17/2022 F 45
4/18/2022 A 23
4/18/2022 B 45
4/18/2022 C 67
4/18/2022 D 78
4/18/2022 E 98
4/18/2022 F 54
First I need to get sum of Amount for each day for last 8 days.
So I used following query.
Select Table_Date,sum(Amount) as Total_Amount from usertable where Table_Date>=DATE(NOW()-INTERVAL 8 DAY) group by Table_Date;
Result
Table_Date Total Amount
4/17/2022 233
4/18/2022 365
Now I need to get the maximum and the minimum after creating this. So I tried as follows,
select max(Total_Amount) from
(
select Table_Date,sum(Amount) as Total_Amount from usertable where Table_Date>=DATE(NOW()-INTERVAL 8 DAY) group by Table_Date
) group by Table_Date;
Seems this is not correct. Can someone show me how to get the output as follows ,
Min =233
Max=365
Note : My server do not support window functions

If I understand correctly, you might need to use aggregate function without group by
SELECT MIN(Total_Amount),
MAX(Total_Amount)
FROM (
Select Table_Date,sum(Amount) as Total_Amount
from usertable
where Table_Date>=DATE(NOW()-INTERVAL 8 DAY)
group by Table_Date
) t1

Related

MySQL Query trying to (CROSS?) JOIN on one table

Been trying to figure this out for a couple hours and hoping for some expert assistance:
I have a single Mysql table with data such as:
Date version amount
2021-03-01 A 100
2021-03-02 A 35
2021-03-02 B 80
2021-03-03 A 7
2021-03-03 B 90
2021-03-03 C 3
2021-03-03 A 8
2021-03-04 B 15
2021-03-04 C 90
2021-03-04 B 10
And trying to get output for each version for every day, with amount populated as '0' for null;
Result:
Date version SUM(amount)
2021-03-01 A 100
2021-03-01 B 0
2021-03-01 c 0
2021-03-02 A 35
2021-03-02 B 80
2021-03-02 C 0
2021-03-03 A 15
2021-03-03 B 90
2021-03-03 C 3
2021-03-04 A 0
2021-03-04 B 25
2021-03-04 C 90
I tried various 'JOIN', 'LEFT JOIN' and 'CROSS JOIN' permutations without success.
SELECT distinct c1.date, c2.version
FROM crash_log c1
LEFT OUTER JOIN crash_log c2 ON c1.date = c2.date
GROUP BY c1.date, c2.version
(not even messing with the SUM, just trying to get all the rows with this one)
For now, I have a script that does this by brute force: gets DISTINCT date, then get DISTINCT version, then do a nested loop and build an array for each combination. One trouble is it's not scalable and seems the web connection is timing out before the process finishes on a large set.
I'm thinking there's one (semi-?) efficient query that can do this, but I haven't been able to figure it out.
Write subqueries to get all the dates and versions. Cross join these to get every combination.
Then left join that with the table to get either the actual value or default to 0 when NULL.
SELECT d.date, v.version, IFNULL(c.sum, 0) AS sum
FROM (
SELECT DISTINCT date
FROM crash_log) AS d
CROSS JOIN (
SELECT DISTINCT version
FROM crash_log) AS v
LEFT JOIN (
SELECT date, version, SUM(amount) AS sum
FROM crash_log
GROUP BY date, version) AS c ON d.date = c.date AND v.version = c.version
ORDER BY d.date, v.version
Just like your script, but in SQL.
Cross join the distinct dates to the distinct versions and left join to the table and finally aggregation:
SELECT d.Date, v.version, COALESCE(SUM(t.amount), 0) sum_amount
FROM (SELECT DISTINCT Date FROM tablename) d
CROSS JOIN (SELECT DISTINCT version FROM tablename) v
LEFT JOIN tablename t
ON t.Date = d.Date AND t.version = v.version
GROUP BY d.Date, v.version

Calculating moving average for different values in a column MySQL

I have a dataset like this:
team date score
A 2011-05-01 50
A 2011-05-02 54
A 2011-05-03 51
A 2011-05-04 49
A 2011-05-05 59
B 2011-05-03 30
B 2011-05-04 35
B 2011-05-05 39
B 2011-05-06 47
B 2011-05-07 50
I want to add another column called MA3 where I can calculate the moving average of scores for the last 3 days. The point that made it tricky is to calculate the MA for each team. The end result should be like this:
team date score MA3
A 2011-05-01 50 null
A 2011-05-02 54 null
A 2011-05-03 51 null
A 2011-05-04 49 51.66
A 2011-05-05 59 51.33
B 2011-05-03 30 null
B 2011-05-04 35 null
B 2011-05-05 39 null
B 2011-05-06 47 34.66
B 2011-05-07 50 40.33
If that would be a single team, I would go on and do:
SELECT team,
year,
AVG(score) OVER (ORDER BY date ASC ROWS 3 PRECEDING) AS MA3
FROM table
You're missing the PARTITION BY clause:
SELECT team,
date,
AVG(score) OVER (
PARTITION BY team
ORDER BY date ASC ROWS 3 PRECEDING
) AS MA3
FROM table
Note that there will always be an average calculation, regardless of the window size. If you want the average to be null if your window size is smaller than 3, you could do it like this:
SELECT team,
date,
CASE
WHEN count(*) OVER w <= 3 THEN null
ELSE AVG(score) OVER w
END AS MA3
FROM table
WINDOW w AS (PARTITION BY team ORDER BY date ASC ROWS 3 PRECEDING)
dbfiddle
Side note
Your next question might be about logical windowing, because often, you don't actually want to calculate the average over 3 rows, but over some interval,
like e.g. 3 days. Luckily, MySQL implements this. You could then write:
WINDOW w AS (PARTITION BY team ORDER BY date ASC RANGE INTERVAL 3 DAY PRECEDING)

Is there a way to have a conditional statement for comparing of tables using MySQL only?

I am having a dilemma from comparing my tables.
My problem is, I want to get each sum, which depends on the pricing. Here is the table.
Main table
main_id main_price main_date_created
25 8.5 2019-08-16
26 11.5 2019-08-01
Total table
id main_id total_price date_generated
1 25 10 2019-08-16
2 25 10 2019-08-17
3 25 10 2019-08-18
4 25 10 2019-08-19
5 25 10 2019-08-20
6 25 10 2019-08-21
7 26 20 2019-08-01
8 26 5 2019-08-02
9 26 5 2019-08-03
10 26 10 2019-08-04
Price History table
id main_id changed_main_price price_date_changed
1 25 15 2019-08-18
2 26 20 2019-08-03
I don't know if there is a way to do this just by using MySQL, what I am trying to achieve is, the Total table will be sum by MONTH and YEAR and will be multiplied by their designated price that depends on the date whether if the price has changed or not . the SUM will from each month will be generated by multiplying with the main price in the Main table but if the price had changed from its original price which it is on the Price history table
The output should be like this if the conditional is possible:
id main_id total_price price_generated (which is the prices) date
1 25 170 (10+10*8.5) 8.5
2 25 610 (10+10+10+10*15) 15
3 26 287.5 (20+5*11.5) 11.5
4 26 300 (5+10*20) 20
Here is my existing query,
SELECT m.main_id
, m.main_price
, SUM(t.total_price) total_generated
, t.date_generated
FROM main m
INNER JOIN total t
ON m.main_id = t.main_id
GROUP
BY MONTH(t.date_generated);
I know that my query is not enough, and I still don't know if my idea is really possible :(.
I racked my brain. hahaha Is this you're after?
SELECT pricelist.id, pricelist.price, SUM(t.total_price), SUM(t.total_price) * pricelist.price,
year( pricelist.latestdate), month(pricelist.latestdate),
year( t.total_date_generated), month(t.total_date_generated)
from totaltable as t
LEFT JOIN (
(
select main_id as id, main_price as price, main_date_created as latestdate
from maintable
)
UNION ALL
(
select total_main_id, changed_main_price , price_date_changed
from pricehistorytable
)
) as pricelist on pricelist.id = t.total_main_id
GROUP BY pricelist.id , t.total_price, pricelist.price,
year( pricelist.latestdate), month(pricelist.latestdate),
year( t.total_date_generated), month(t.total_date_generated) ;

Summing data for last 7 day look back window

I want a query that can give result with sum of last 7 day look back.
I want output date and sum of last 7 day look back impressions for each date
e.g. I have a table tblFactImps with below data:
dateFact impressions id
2015-07-01 4022 30
2015-07-02 4021 33
2015-07-03 4011 34
2015-07-04 4029 35
2015-07-05 1023 39
2015-07-06 3023 92
2015-07-07 8027 66
2015-07-08 2024 89
I need output with 2 columns:
dateFact impressions_last_7
query I got:
select dateFact, sum(if(datediff(curdate(), dateFact)<=7, impressions,0)) impressions_last_7 from tblFactImps group by dateFact;
Thanks!
If your fact table is not too big, then a correlated subquery is a simple way to do what you want:
select i.dateFact,
(select sum(i2.impressions)
from tblFactImps i2
where i2.dateFact >= i.dateFact - interval 6 day
) as impressions_last_7
from tblFactImps i;
You can achieve this by LEFT OUTER JOINing the table with itself on a date range, and summing the impressions grouped by date, as follows:
SELECT
t1.dateFact,
SUM(t2.impressions) AS impressions_last_7
FROM
tblFactImps t1
LEFT OUTER JOIN
tblFactImps t2
ON
t2.dateFact BETWEEN
DATE_SUB(t1.dateFact, INTERVAL 6 DAY)
AND t1.dateFact
GROUP BY
t1.dateFact;
This should give you a sliding 7-day sum for each date in your table.
Assuming your dateFact column is indexed, this query should also be relatively fast.

MYSQL: sum mysql rows by specific character and add the results into an equation

Please I have a single table where it has 3 columns like the below:
id value type
-----------------
1001 -10 L
1002 20 W
1003 -21 L
1004 -29 L
1005 12 D
1006 19 W
1007 18 W
1008 15 W
1009 88 O
1010 11 N
1011 44 S
I want to count values of each type sum them up after that in this way:
L + W + D + O = TOTAL (To have a clear total of all the specified types.)
Answer:
SELECT SUM(total) from (
select sum(value) as total from table where type = 'L'
union all
select sum(value) as total from table where type = 'W'
union all
select sum(value) as total from table where type = 'D'
union all
select sum(value) as total from table where type = 'O'
)a
Thanks for all who took time to review my question. I figured it out my way and posted the answer to help anyone who had the same question or would have the same in the future. Thanks for all the answers as well :)).