简体   繁体   中英

Using recursive sql query not for parent-child

I'm not new in sql and t-sql, but at past I've never used recursive query - all problems were solved with WHILE or CURSOR. I just got 1 question - how to organaze recursion query for following problem: I want to manipulate with last row of data in certain partition. Can't understand how to stop my recursion at last level of partition.

CREATE TABLE #temp
(i int
, s int
, v int);

INSERT INTO #temp

SELECT 1, 1, 10
UNION
SELECT 1, 2, 20
UNION
SELECT 2, 1, 5
UNION
SELECT 2, 2, 5
UNION
SELECT 2, 3, 2

WITH CTE AS

(
SELECT i
, s
, v
FROM #temp
WHERE s=1

UNION ALL

SELECT t.i
, t.s
, t.v + cte.v as new_v
FROM #temp t
INNER JOIN cte
ON (cte.i=t.i)
WHERE t.s>1
)

SELECT *
FROM cte

OPTION(MAXRECURSION 0)

I want to get 5 rows as result:

result

I know that it could be solved with OUTER APPLY, JOINS, WHILE or CURSOR methods. Could you please share any features for my to understand how to get same result with recurcive cte query? SUM function there is just for example - for that problem recurcive query is best way cause I will use many scalar functions in big CASE which will use value from last row in partition and value of current row partition.

Thanks. Sorry for my bad english level.

Will it be correctly if I'll try same problem with following example? I guess that need to correctly say in which order way recursive query gonna do any data manipulating. So below code which will help you understand what did I want to solve:

CREATE TABLE #temp
(i_key int
, step int
, step_h int
, value int);

INSERT INTO #temp

SELECT 1, 1, NULL, 20
UNION
SELECT 1, 2, 1, 20
UNION
SELECT 2, 1, NULL, 10
UNION
SELECT 2, 2, 1, 10
UNION
SELECT 2, 3, 2, 5

WITH CTE AS

(
SELECT i_key
, step
, value
FROM #temp
WHERE step=1
--AND i_key=2

UNION ALL

SELECT t.i_key
, t.step
, CASE
        WHEN cte.value - t.value <=0 THEN 0
        ELSE cte.value - t.value
END as value
FROM #temp t
INNER JOIN cte
ON (cte.i_key=t.i_key
AND cte.step=t.step_h)
--WHERE t.step>1
)

SELECT *
FROM CTE

OPTION(MAXRECURSION 0)

Is parent-child structure always need for solving this problems? So i guess it could be done with another join (without column of parent-child).

AND cte.step=t.step-1

For your particular example, recursion is unnecessary. All you need is SQL Server 2012 or later version:

select t.*,
    sum(t.v) over(partition by t.i order by t.s) as [RT]
from #temp t
order by t.i, t.s;

If you need to access previos / next row, there are lag() / lead() ranking functions that were introduced in the same aforementioned version of SQL Server.

EDIT: Ah, I see. You simply want to know how to write recursive CTEs properly. Here is a (seemingly) correct code for your second example:

with cte as (
    select t.i_key, t.step, t.value
    from @temp t
    where t.step_h is null
    union all
    select c.i_key, t.step, case
        when c.value < t.value then 0
        else c.value - t.value
    end as [Value]
    from @temp t
        inner join cte c on c.step = t.step_h
            and c.i_key = t.i_key
)
select *
from cte c
order by c.i_key, c.step;

In the end, it stops by itself when an iteration does not produce any new rows.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM