Рассчитать значения строк в таблице, используя предыдущие значения - PullRequest
0 голосов
/ 21 января 2020

У меня есть две таблицы, которые структурированы следующим образом:

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|
+---+---+

Мне нужно написать запрос SQL, который вычисляет заполнение столбца val в table2, так что

val = prev_value^2 + prev_value^0.5

, где prev_value - это просто значение столбца val в предыдущей строке (id -1). Таким образом, для первой строки в table2 значение val должно быть

val = 1.6^2 + 1.6^0.5 = 3.82 

Этот результат 3.82 будет использоваться для вычисления val для строки с id == 8 в table2 и так далее.

Я попытался сделать следующее,

select df2.*
       , power(df1.val, 2) + power(df1.val, 0.5) as sum_val 
from  df1, df2 
where df1.id = df2.id - 1

, но это возвращает только одну строку

+---+---+------------------+
| id|val|           sum_val|
+---+---+------------------+
|  7|  0|3.8249110640673525|
+---+---+------------------+

, которая является правильным выводом, но я ищу способ получить все строки в table2 вычисляются одновременно.

Есть ли способ сделать это в SQL? Я использую SQL запросов в pyspark.

Ответы [ 2 ]

1 голос
/ 21 января 2020

Сделать это как обновление для второй таблицы немного сложно. Вот одно из решений:

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;

Здесь - это дб <> скрипка.

1 голос
/ 21 января 2020

Пример для MySQL 8.x.

Запрос заполняет все значения поля val, имеющие нулевые или NULL-значения, расчетными.

Если начальные значения необходимо заполнить, они заполняются нулями.

id значения могут начинаться с любого значения.

Пробелы в последовательности значений id недопустимы (отредактируйте рекурсивную часть CTE, если вам нужно снять это ограничение).

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;

fiddle

...