简体   繁体   中英

getting the difference between two rows and perform mathematical operation on the difference mysql

My data set for example looks like this

ID|Value
 1|10
 1|3
 2|9
 2|10
 2|15

I need to find the difference between two consecutive elements of the same ID and store the value and then again find the difference and multiply the stored value with the new difference all of values with the same ID. This must go on till there are elements with the same ID. Hence my final data set should looklike

ID|Value
 1|-7
 2|5

Does anyone have any suggestions how i should go about this using sql

Calculating the differences between consecutive rows -

MariaDB [sandbox]> SELECT T.*,
    -> IF(T.TID <> @P ,@RN:=1,@RN:=@RN+1) RN,
    -> IF(T.TID <> @P ,0, @PVAL) PVAL,
    -> IF(T.TID <> @P ,0, T.VALUE * 1.00 - @PVAL) DIFF,
    -> @P:=T.TID,
    -> @PVAL:=T.VALUE
    -> FROM(SELECT @RN:=0,@P:=0,@PVAL:=0.00,@DIFF:=0.00) RN,T
    -> ORDER BY T.TID,T.dt;
+------------+------+-------+------+------+------+-----------+----------------+
| dt         | TID  | Value | RN   | PVAL | DIFF | @P:=T.TID | @PVAL:=T.VALUE |
+------------+------+-------+------+------+------+-----------+----------------+
| 2017-01-01 |    1 |    10 |    1 | 0    |    0 |         1 |             10 |
| 2017-01-02 |    1 |     3 |    2 | 10   |   -7 |         1 |              3 |
| 2017-01-01 |    2 |     9 |    1 | 0    |    0 |         2 |              9 |
| 2017-01-02 |    2 |    10 |    2 | 9    |    1 |         2 |             10 |
| 2017-01-03 |    2 |    15 |    3 | 10   |    5 |         2 |             15 |
+------------+------+-------+------+------+------+-----------+----------------+
5 rows in set (0.00 sec)

BUT there is no aggregation function in sql (any version as far as I know) that will calculate the product (if that's the right word) of the differences. What's more you seem to want to discard the first row for every tid. You could do this by group_concatenating the differences into a table and then calling a stored procedure which initiates a call to dynamic sql (you cannot use dynamic sql in stored functions by the way).

This stored procedure

drop procedure if exists f;
delimiter //

CREATE DEFINER=`root`@`localhost` procedure `F`(
    instring varchar(200)
)

LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
begin
declare   tempstring varchar(100);
declare   outstring  varchar(100);
declare  tempid int;
declare  checkit int;
declare maxrecs int;
set checkit = 0;
set maxrecs = (select count(*) from temp);

looper: while   checkit < maxrecs do
select tid,calc into    tempid,tempstring from temp limit checkit,1; 
set checkit = checkit + 1;  
if instr(tempstring,',')  = 0 then 
    update temp
    set    rsult  = tempstring; 
else
    set outstring  = replace(tempstring,',','*');
    set outstring  = concat('update temp set rsult = (Select ',outstring,') where tid = ', tempid, ';');
    set @sqlstmt = outstring;
    #select checkit, maxrecs, outstring;
    prepare sqlstmt from @sqlstmt;  
    execute sqlstmt;
    deallocate prepare sqlstmt;
end if;

end while;
end //

delimiter ;

when called in this script produces your desired outcome

*ariaDB [sandbox]> drop table if exists temp;
Query OK, 0 rows affected (0.09 sec)

MariaDB [sandbox]> create table temp as
    -> select s.tid,group_concat(s.diff) calc, 1.00 as rsult
    -> from
    -> (
    -> SELECT T.*,
    -> IF(T.TID <> @P ,@RN:=1,@RN:=@RN+1) RN,
    -> IF(T.TID <> @P ,0, @PVAL) PVAL,
    -> IF(T.TID <> @P ,0, T.VALUE * 1.00 - @PVAL) DIFF,
    -> @P:=T.TID,
    -> @PVAL:=T.VALUE
    -> FROM(SELECT @RN:=0,@P:=0,@PVAL:=0.00,@DIFF:=0.00) RN,T
    -> ORDER BY T.TID,T.dt
    -> ) s
    -> where s.rn <> 1
    -> group by s.tid;
Query OK, 2 rows affected (0.23 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]> call f('1');
Query OK, 0 rows affected (0.07 sec)

MariaDB [sandbox]>
MariaDB [sandbox]> select * from temp;
+------+-----------+-------+
| tid  | calc      | rsult |
+------+-----------+-------+
|    1 | -7.00     | -7.00 |
|    2 | 1.00,5.00 |  5.00 |
+------+-----------+-------+
2 rows in set (0.00 sec)*

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