Update Column from Recursive CTE (MySQL/MariaDB) [closed]
-
15-03-2021 - |
Question
I need to update the same table I'm using to create a recursive cte. The cte works as a select statement, but I can't get it to actually insert those values back into the table.
My code is below- basically I want to:
UPDATE tbl_1min
SET tbl_1min.ema9 = x.NewEma
WHERE x.id = tbl_1min.id
Can anyone help? I'd really appreciate it!
SET @NDays := 9;
WITH RECURSIVE anchor AS
(
SELECT
a1.id,
a1.close,
a1.ema9
FROM
tbl_1min a1
),
x AS
(
SELECT
anchor.id,
anchor.close,
x2.ema9 AS PrevEma,
anchor.ema9,
anchor.ema9 AS NewEma
FROM
anchor
INNER JOIN
anchor x2
ON
anchor.id - 1 = x2.id
WHERE anchor.id = @NDays -- FIRST SEED ROW
UNION
SELECT
anchor.id,
anchor.close,
x.PrevEma,
anchor.ema9,
(((2 / (1 + @NDays)) * (anchor.close - x.PrevEma)) + x.PrevEma) AS NewEma
FROM
x
JOIN anchor
ON anchor.id = x.id + 1 -- `X` WALKS ITSELF
)
SELECT
id,
NewEma
FROM
x
ORDER BY x.id
;
Solution
For this, I changed the recursive CTE to have both the anchor and child in the same CTE as that is standard. With that, I was able to show how the original table gets updated.
The answer consists of 3 parts as it pertains to the query:
- A query to show the original contents of the table
- The update based on the recursive CTE
- A query of the original table showing the update - in this case, the 2 rows.
Update based on your other questions
CREATE TABLE tbl_1min(id int, close1 int,ema9 double);
INSERT INTO tbl_1min VALUES
(1,1,10),
(2,1,15),
(3,1,25),
(4,1,30),
(5,1,35),
(6,1,40),
(7,1,45),
(8,1,50),
(9,1,55),
(10,1,60),
(11,1,65);
select * from tbl_1min;
SET @NDays := 9;
WITH RECURSIVE cte AS
(
SELECT a.id, a.close1, a.ema9 AS PrevEma, a.ema9, a.ema9 AS NewEma
FROM tbl_1min a
WHERE a.id = @NDays -- FIRST SEED ROW
UNION ALL
SELECT y.id, y.close1, x.NewEma AS PrevEma, y.ema9,
((2 / (1 + @NDays) * (y.close1 - x.NewEma)) + x.NewEma) AS NewEma
FROM cte x JOIN tbl_1min y ON y.id = x.id + 1 -- `X` WALKS ITSELF
)
Understand the result of the CTE by putting the below line right after the CTE and run - look at #s 10 and 11.
select * from cte order by id
Once you have reviewed the results of the CTE, remove the select statement for the CTE, run again and replace with the update and the select to see the data post-update.
UPDATE tbl_1min, cte SET tbl_1min.ema9 = cte.NewEma
WHERE cte.id = tbl_1min.id;
select * from tbl_1min;
OTHER TIPS
You can use any query typo with the created (with statements
The update can be de by joining the original with the cnstructed
CREATE tABLE tbl_1min(id int, close int,ema9 varchar(30))
INSERT INTO tbl_1min VALUES (1,1,'test')
SET @NDays := 9; WITH RECURSIVE anchor AS ( SELECT a1.id, a1.close, a1.ema9 FROM tbl_1min a1 ), x AS ( SELECT anchor.id, anchor.close, x2.ema9 AS PrevEma, anchor.ema9, anchor.ema9 AS NewEma FROM anchor INNER JOIN anchor x2 ON anchor.id - 1 = x2.id WHERE anchor.id = @NDays -- FIRST SEED ROW UNION SELECT anchor.id, anchor.close, x.PrevEma, anchor.ema9, (((2 / (1 + @NDays)) * (anchor.close - x.PrevEma)) + x.PrevEma) AS NewEma FROM x JOIN anchor ON anchor.id = x.id + 1 -- `X` WALKS ITSELF ) UPDATE tbl_1min t1 INNER JOIN x ON t1.id = x.id SET t1.ema9 = x.NewEma;
SELECT * FROM tbl_1min
id | close | ema9 -: | ----: | :--- 1 | 1 | test
db<>fiddle here