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.