Tsql 迭代CTE求解

Tsql 迭代CTE求解,tsql,sql-server-2005,common-table-expression,Tsql,Sql Server 2005,Common Table Expression,我一直在开发一个CTE,它可以根据一些工作项目有效地创建发票行。鉴于: Create table JobLines (line int, code varchar(10), qty decimal(9,2)) go insert into JobLines values (1, '2222A', 1) insert into JobLines values (2, '2222B', 3) insert into JobLines values (3, '2222A', -1)

我一直在开发一个CTE,它可以根据一些工作项目有效地创建发票行。鉴于:

Create table JobLines (line int, code varchar(10), qty decimal(9,2))  
go

insert into JobLines values (1, '2222A', 1)  
insert into JobLines values (2, '2222B', 3)  
insert into JobLines values (3, '2222A', -1)  
insert into JobLines values (4, '2222C', 2)  
insert into JobLines values (5, '2222D', 1)  
insert into JobLines values (6, '2222B', -1)  
insert into JobLines values (7, '2222A', 2)  
insert into JobLines values (8, '2222B', -1)  
insert into JobLines values (9,'2222A', -1)  
go
我想要一台CTE,它可以: 在与代码匹配之前,从正行减去每一个负行

结果应该是: 第1行-0减去第3行。 第2行-1减去第6行和第8行。 第4行-无变化。 第5行-无变化。 第7行-1减去第9行

有几次我差一点就到了。主要的问题是,我无法得到第2行或第7行所需的结果,因为我无法有效地将需要减去的2行组合在一起

我的方法是尝试在正行上迭代,获取每行的负行

我正在处理的示例代码:

;with cte_positive_rows as (select line, code, qty
    ,row_number() over (partition by code order by line) code_instance
    ,row_number() over (order by line) row_sequence
from jobLines
where qty > 0
)
,cte_negative_rows as (
    select line, code, qty
    ,row_number() over (partition by code order by line) code_instance
    ,row_number() over (order by line) row_sequence
from jobLines
where qty < 0
)
,cte_iterator as(
--base case - start with line 1 from cte_postive_rows...

select min(base.line) line, base.code
    ,cast(sum(base.qty + neg.qty) as     decimal(9,2)) total_qty
    ,base.code_instance
    ,base.row_sequence, base.row_sequence + 1 as next_row
    from cte_positive_rows base
    inner join cte_negative_rows neg
    on
    neg.row_sequence = base.row_sequence
    and neg.code_instance = base.code_instance
    where base.row_sequence = 1
    group by base.code, base.code_instance, base.row_sequence

    union all

    --iterative case - each line..
    -- the iterative case should returns all the rows that needed modifying

    select row.line, row.code
    ,cast(row.qty + neg.qty as decimal(9,2)) qty, row.code_instance
    ,row.row_sequence
    ,row.row_sequence + 1 as next_row
    from cte_positive_rows row 
    inner join cte_negative_rows neg
    on
    neg.row_sequence = row.row_sequence
    and neg.code_instance = row.code_instance
    inner join cte_iterator cte
    on row.row_sequence = cte.next_row
)

-- get all the modified and non-modifed rows with joins

select pos.line, pos.code, pos.qty, pos.code_instance, pos.row_sequence
from cte_positive_rows pos
left outer join cte_iterator i
on pos.row_sequence = i.row_sequence
where i.row_sequence IS NULL
union all 
select line, code, total_qty, code_instance, row_sequence from cte_iterator
order by row_sequence

我的梦想可能吗

我不确定我是否完全理解您的需求,但这似乎满足了您的需求:

select line, code, qty + isnull((
    -- get the sum of all negative values...
    select sum(j1.qty)
    from JobLines j1
    where 
        -- ...for the same code, but with a higher line number...
        j1.code = PositiveLines.code and 
        j1.line > PositiveLines.line and 
        j1.qty < 0 and
        -- ...where there is no positive value on a previous line
        not exists (
            select * 
            from JobLines
            where 
                code = j1.code and 
                qty > 0 and 
                line > j1.line)
    ),0)
from
(   
select
    line, code, qty
from
    JobLines
where
    qty > 0
) PositiveLines

也许我需要以某种方式使用交叉应用来正确地为负行设置关键帧,但更复杂的是。可能有教育意义。谢谢,我来看看。您能找到一种方法使code_实例在负行上作为更好的键执行吗?非常好,谢谢。我被CTE追得太多了。。在这种情况下,工作的工具似乎是错误的。对于学习来说,看到它以这种方式实现仍然是很好的,但这非常有效-不能与结果争论!比我决定走的路简单得多:该死——回到这里,它只适用于问题数据。如果引入第10行,或删除第9行,则该行不起作用
1   2222A   0.00    1   1
2   2222B   2.00    1   2
4   2222C   2.00    1   3
5   2222D   1.00    1   4
7   2222A   2.00    2   5
select line, code, qty + isnull((
    -- get the sum of all negative values...
    select sum(j1.qty)
    from JobLines j1
    where 
        -- ...for the same code, but with a higher line number...
        j1.code = PositiveLines.code and 
        j1.line > PositiveLines.line and 
        j1.qty < 0 and
        -- ...where there is no positive value on a previous line
        not exists (
            select * 
            from JobLines
            where 
                code = j1.code and 
                qty > 0 and 
                line > j1.line)
    ),0)
from
(   
select
    line, code, qty
from
    JobLines
where
    qty > 0
) PositiveLines