Let`s say I have the following table
+----+-------+
| Id | Value |
+----+-------+
| 1 | 2.0 |
| 2 | 8.0 |
| 3 | 3.0 |
| 4 | 9.0 |
| 5 | 1.0 |
| 6 | 4.0 |
| 7 | 2.5 |
| 8 | 6.5 |
+----+-------+
I want to plot these values, but since my real table has thousands of values, I thought about getting and average for each X rows. Is there any way for me to do so for, ie, each 2 or 4 rows, like below:
2
+-----+------+
| 1-2 | 5.0 |
| 3-4 | 6.0 |
| 5-6 | 2.5 |
| 7-8 | 4.5 |
+-----+------+
4
+-----+------+
| 1-4 | 5.5 |
| 5-8 | 3.5 |
+-----+------+
Also, is there any way to make this X value dynamic, based on the total number of rows in my table? Something like, if I have 1000 rows, the average will be calculated based on each 200 rows (1000/5), but if I have 20, calculate it based on each 4 rows (20/5).
I know how to do that programmatically, but is there any way to do so using pure SQL?
EDIT: I need it to work on mysql.
Depending on your DBMS, something like this will work:
SELECT
ChunkStart = Min(Id),
ChunkEnd = Max(Id),
Value = Avg(Value)
FROM
(
SELECT
Chunk = NTILE(5) OVER (ORDER BY Id),
*
FROM
YourTable
) AS T
GROUP BY
Chunk
ORDER BY
ChunkStart;
This creates 5 groups or chunks no matter how many rows there are, as you requested.
If you have no windowing functions you can fake it:
SELECT
ChunkStart = Min(Id),
ChunkEnd = Max(Id),
Value = Avg(Value)
FROM
YourTable
GROUP BY
(Id - 1) / (((SELECT Count(*) FROM YourTable) + 4) / 5)
;
I made some assumptions here such as Id beginning with 1 and there being no gaps, and that you would want the last group too small instead of too big if things didn't divide evenly. I also assumed integer division would result as in Ms SQL Server.
You can use modulos operator to act on every Nth row of the table. This example would get the average value for every 10th row:
select avg(Value) from some_table where id % 10 = 0;
You could then do a count of the rows in the table, apply some factor to that, and use that value as a dynamic interval:
select avg(Value) from some_table where id % (select round(count(*)/1000) from some_table) = 0;
You'll need to figure out the best interval based on the actual number of rows you have in the table of course.
EDIT: Rereading you post I realize this is getting an average of every Nth row, and not each sequential N rows. I'm not sure if this would suffice, or if you specifically need sequential averages.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With