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
;
Was it helpful?

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:

  1. A query to show the original contents of the table
  2. The update based on the recursive CTE
  3. 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

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top