Average with partial data in SQL - mysql

I have data as below, which is partial and few rows are missing. I need an average with data considering the previous available value. Do we have any function available for such an average in sql? 
Needed average: 220 
Available data for 10 days:
1st day: 100
4th day: 200
7th day: 300
10th day: 400
Putting the same in a table format:
Rows Date Partial Continuous(needed)
1 01-Aug-18 100 100
2 100
3 100
4 04-Aug-18 200 200
5 200
6 200
7 07-Aug-18 300 300
8 300
9 300
10 10-Aug-18 400 400
-----------------------------------
Average 250 220
-----------------------------------
I am looking at something like select avg(partial*(nextdate-date))/(lastdate-firstdate) from mytable;

Use a user-defined variable to fill in the missing values.
SELECT AVG(normal)
FROM (SELECT IFNULL(continuous, #prev) AS normal, #prev := IF(continuous IS NULL, #prev, continuous)
FROM (SELECT continuous
FROM yourTable
ORDER BY id) AS x
CROSS JOIN (SELECT #prev := NULL) AS y
) as z

What about AVG()?
> SELECT AVG(Normal) FROM table WHERE something;

Related

cumulative sum till target reached in mysql

I have following tables,
Workout Data:
Date User Distance Calories
1614944833 1 100 32
1614944232 2 100 43
1624944831 1 150 23
1615944832 3 250 63
1614644836 1 500 234
1614954835 2 100 55
1614344834 3 100 34
1614964831 1 260 23
1614944238 1 200 44
user_subdomain Data:
User sub_domain
1 3
2 3
3 3
4 2
Subdomain data:
subdomain name
3 test1
4 test2
I would like to get sum value of distance,calories,count of records once they user reached sum of distance >= 1000.we should not count remaining records if user crossed 1000 distance.( if user crossed 1000,then 1000 else max distance value).
Expected Output:
Date record_count Distance Calories
1614964831 4 1000 312
1614954835 2 200 98
1614344834 3 350 97
So This result shows each users total effort they used to reach distance 1000 by record_count,then if they reached 1000 above then calculated as 1000,else max reached distance value,then total sum of that calories till 1000 cumulative sum reached.This is the output i need to retrieve.I tried with below query,but not works
Can anyone suggest with cumulative sum inner join method or any other solution for this?
Since MySQL 8.0 you can use window functions in next way:
with cumulative as (
-- calculate cumulative Distance & Calories
select
User,
Distance,
Calories,
sum(Distance) over (partition by User order by Date) SumDistance,
sum(Calories) over (partition by User order by Date) SumCalories
from Workout
order by User, Date
) select
User, max(SumDistance), max(SumCalories)
from cumulative
where SumDistance - Distance < 1000 -- filter
group by User;
MySQL window functions

MySQL Select records exceeding the cumulative total

Given I have following table
Id
FileSizeMB
1
100
2
100
3
100
4
100
5
100
6
100
I want to select oldest records exceeding a cumulative value, in this case say 500.
So something like this
Id
Cumulative_FileSizeMB
6
100
5
200
4
300
3
400
2
500
1
600
I want to select only records with id 2 and 1 as they are >= 500.
Goal is to delete them.
Thanks
For anyone with same problem.
I have reached this solution using Mysql window functions,
and also there is no need to declare a variable for cumulative total
SELECT * from (
SELECT
id,
FileSizeMB,
SUM(FileSizeMB) OVER (ORDER BY id DESC) AS TotalFileSizeMB
FROM table
) as t1
WHERE TotalFileSizeMB > 500

How to find the smallest value in a row

i need help to create a sql query that can find the smallest value in 1 row , and display it in the last column, like this table.
id
out
mid
in
Smallest
1
200
100
50
50
2
100
150
50
50
3
200
100
250
100
4
50
100
150
50
5
50
100
100
50
6
20
200
100
20
7
-
-
100
100
8
150
-
100
100
this is my query :
On MySQL you may use the scalar LEAST() function:
SELECT id, `out`, mid, `in`, LEAST(`out`, mid, `in`) AS Smallest
FROM yourTable;
If your database doesn't have a LEAST function, we can use a CASE expression as an alternative:
SELECT id, `out`, mid, `in`,
CASE WHEN `out` < mid AND `out` < `in` THEN `out`
WHEN mid < `in` THEN mid
ELSE `in` END AS Smallest
FROM yourTable;
Side note: Both IN and OUT are reserved MySQL keywords, and you should avoid naming your columns with them.

SQL Query to get number of times and duration of a column values reaches a specific value in a sequence

I have a table with two columns ReceivedOn(Date/Time) and Speed(int)
Sample data will look like below
ReceivedOn | Speed
----------------------------------------------
2012-11-05 06:30:00 10
2012-11-05 06:31:00 45
2012-11-05 06:32:00 48
2012-11-05 06:33:00 53
2012-11-05 06:34:00 47
2012-11-05 06:35:00 38
2012-11-05 06:36:00 22
2012-11-05 06:37:00 36
2012-11-05 06:38:00 41
2012-11-05 06:39:00 47
2012-11-05 06:40:00 49
2012-11-05 06:41:00 22
2012-11-05 06:42:00 36
I need to group the rows when speed > 40, so that the resulting output would be
StartTime | EndTime | Count
--------------------------------------------------------
2012-11-05 06:31:00 2012-11-05 06:34:00 4
2012-11-05 06:38:00 2012-11-05 06:40:00 3
StartTime to be the ReceivedOn value when the speed first crossed 40, and the EndTime value to be the ReceivedOn value when it was last over 40 in consecutive records, with the Count being the total number of consecutive records that were over 40.
I tried my best but unable to get it. Is it possible to get this with sql query?
Please suggest. Thanks in advance.
Here's a general answer to questions like these.
Detect consecutive items meeting particular criteria in a time series
Your specific case seems to be easier because you have no time gaps (said he hopefully). You are trying to find the gaps in your time sequence. In your case the gaps are defined as those items that are >= 40. So, you're looking for gaps in the sequence of events with values less than forty.
Here's a query that gives your time squence with row numbers.
SELECT #RowA := #RowA + 1 AS ROWNUM,
ReceivedOn, Speed
FROM (
SELECT ReceivedOn, Speed
FROM obs
WHERE NOT Speed >= 40
) AS A
JOIN (SELECT #RowA := 0) AS B
Now you use a some serious SQL monkey business to self-join this sequence to itself. That works like this:
SELECT B.ReceivedON + INTERVAL 1 MINUTE As StartTime,
A.ReceivedOn - INTERVAL 1 MINUTE AS EndTime,
-1 + TIMESTAMPDIFF(MINUTE, B.ReceivedOn, A.ReceivedOn) AS Count
FROM (
SELECT #RowA := #RowA + 1 AS ROWNUM,
ReceivedOn, Speed
FROM (
SELECT ReceivedOn, Speed
FROM obs
WHERE NOT Speed >= 40
) AS A
JOIN (SELECT #RowA := 0) AS B
) AS A
JOIN (
SELECT #RowB := #RowB + 1 AS ROWNUM,
ReceivedOn, Speed
FROM (
SELECT ReceivedOn, Speed
FROM obs
WHERE NOT Speed >= 40
) AS A
JOIN (SELECT #RowB := 0) AS B
) AS B ON B.ROWNUM+1 = A.ROWNUM
WHERE TIMESTAMPDIFF(MINUTE, B.ReceivedOn, A.ReceivedOn) > 1
http://sqlfiddle.com/#!2/2cb57/24/0
This looks really hairy, but it is simply a join of that first query to itself ON B.ROWNUM+1 = A.ROWNUM. That lines up that query's result set to itself offset by one row, so you can compare consecutive rows.
That gives the result you need. Notice that if your first observation is >= 40, this query will leave out the first sequence of observations.

MySQL query that gets all rows UNTIL the SUM(column) is bigger than X

I have the following data
user_id days date
88 2 2013-08-25
88 4 2013-08-23
88 18 2013-08-5
88 1 2013-08-4
88 2 2013-08-2
73 11 2013-08-2
299 4 2013-08-2
12 983 2013-08-2
I'm trying to get all recent rows (order by DATE desc) for a specific user_id , until the SUM of days column is bigger than X. For example in this case if X=7 I would get the three first rows with SUM(days)=24.
Try this. Here you will use a local variable that will count the sums in the subquery.
select
user_id,
days,
date
from
(
select
user_id,
days,
date,
#sum_days := #sum_days + days as sum_days
from
myTable
order by
date desc
) t
cross join (select #sum_days := 0) const -- resetting your #sum_days var.
where
sum_days < X -- fill a number in for X here.