Reputation: 7977
I have the two tables which are structured like this -
table 1
+---+---+
| id|val|
+---+---+
| 1|1.1|
| 2|1.2|
| 3|1.3|
| 4|1.4|
| 5|1.5|
| 6|1.6|
+---+---+
table2
+---+---+
| id|val|
+---+---+
| 7| 0|
| 8| 0|
| 9| 0|
+---+---+
I need to write a SQL query that calculates the populates the val
column in table2
, such that
val = prev_value^2 + prev_value^0.5
where prev_value
is simply the value of the val
column in the previous row(id -1
). So for the first row in table2
the value of val
should be
val = 1.6^2 + 1.6^0.5 = 3.82
This result 3.82
will be used to calculate the val
for the row with id == 8
in table2
and so on.
I tried doing the following,
select df2.*
, power(df1.val, 2) + power(df1.val, 0.5) as sum_val
from df1, df2
where df1.id = df2.id - 1
but this returns only one row
+---+---+------------------+
| id|val| sum_val|
+---+---+------------------+
| 7| 0|3.8249110640673525|
+---+---+------------------+
which is the correct output but I am looking for a way to get all the rows in table2
computed at once.
Is there a way to do this in SQL? I am using SQL queries in pyspark.
Upvotes: 0
Views: 240
Reputation: 1271111
Doing this as an update on a second table is a bit tricky. Here is one solution:
with recursive cte as (
(select t1.val as val, 0 as lev
from table1 t1
order by id desc
limit 1
) union all
select sqrt(cte.val) + power(cte.val, 2), lev + 1
from cte
where lev < (select count(*) from table2)
)
update table2 t2 join
(select t2.id, row_number() over (order by id) as seqnum
from table2 t2
) tt2
on tt2.id = t2.id join
cte
on tt2.seqnum = cte.lev
set t2.val = cte.val;
Here is a db<>fiddle.
Upvotes: 1
Reputation: 42844
An example for MySQL 8.x.
The query fills all values of val
field having zero or NULL values with calculated ones.
If starting value(s) needs to be filled they're filled with zero(es).
id
values may start from any value.
The gaps in id
values sequence are not allowed (edit recursion part of CTE if you need to remove this restriction).
WITH RECURSIVE
cte AS ( ( SELECT id, COALESCE(val, 0) val
FROM test
ORDER BY id
LIMIT 1 )
UNION ALL
SELECT cte.id + 1, CASE WHEN COALESCE(test.val,0) = 0
THEN pow(cte.val,2)+pow(cte.val,0.5)
ELSE test.val
END
FROM cte
LEFT JOIN test ON test.id = cte.id + 1
WHERE cte.id < ( SELECT MAX(id)
FROM test ) )
UPDATE test
JOIN cte USING (id)
SET test.val = cte.val
WHERE COALESCE(test.val,0) = 0;
Upvotes: 1