简体   繁体   中英

stored procedure returning a calculated resultset

i have a table like this

from   | to     | value
-----------------------
08:10  | 08:12  | 2
08:13  | 08:20  | 5
08:30  | 08:45  | 3
08:46  | 08:55  | 1

and i need to group by intervals of say 1, 10, 60 minutes and get the average value, assuming each minute has one value.

Note: there are holes between the ranges and from is inclusive, to non inclusive

from   | to     | average_value
-----------------------
08:10  | 08:19  | 4
08:20  | 08:29  | 5
08:30  | 08:39  | 3
08:40  | 08:49  | 2
08:50  | 08:59  | 1

My idea was to use a stored procedure to transform the entries to

time   | value
-----------------------
08:10  | 2
08:11  | 2
08:12  | 2
08:13  | 5
...
08:20  | 5
08:30  | 3
...
08:45  | 3
08:50  | 1
...
08:55  | 1

my first attempt

DELIMITER $$
CREATE PROCEDURE Decompose()
BEGIN
    DECLARE num_rows INT;
    DECLARE from DateTime;
    DECLARE to DateTime;
    DECLARE value double;

    DECLARE friends_cur CURSOR FOR SELECT from, to, value FROM sourcetable;

    -- 'open' the cursor and capture the number of rows returned
    -- (the 'select' gets invoked when the cursor is 'opened')
    OPEN friends_cur;
    select FOUND_ROWS() into num_rows;

    WHILE num_rows > 0 DO

        FETCH friends_cur INTO  from, to, value;

        SELECT from, value;

        SET num_rows = num_rows - 1;
    END WHILE;

    CLOSE friends_cur;
END$$
DELIMITER ;

leads to 'Command out of sync' error because each SELECT in the loop will create a new resultset everytime instead of returning a row.

Questions:

  • can i make the stored procedure work somehow?
  • is there a sql possible to get the average value for each interval?

I think your fundamental plan is sound.

I would start by creating a numbers table. ( Creating a "Numbers Table" in mysql )

From that, convert that into a table with rows for each minute of the day for which you wish to calculate the average values - including those that don't have any value - and a column to indicate which interval that particular minute belongs to

Time     Interval
08:00    1
08:01    1
08:02    1
08:03    1
08:04    1
08:05    2
08:06    2
....

And from that left join to your sample table using

ON intervals.Time >= Samples.Time and intervals.Time<Sample.Time

to produce a query of the intervals, then do the average against that.

I don't think you need the cursor.

(I would give more concrete examples, but I lack knowledge of some of MySql variety of SQL intricacies)

may be you can try something like this in a single query:

SELECT DATE_FORMAT(TIMEDIFF('08:12','08:10'), '%m') AS time, AVG(value) avg_value
FROM table_name
GROUP BY 1
ORDER BY avg_value DESC;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM