2010-06-08 46 views
2

我有列的数据库中查找,如:PostgreSQL的功能遍历许多行/法与国家

session | order | atype | amt 
--------+-------+-------+----- 
1  | 0 | ADD | 10 
1  | 1 | ADD | 20 
1  | 2 | SET | 35 
1  | 3 | ADD | 10 
2  | 0 | SET | 30 
2  | 1 | ADD | 20 
2  | 2 | SET | 55 

它代表的行为发生。每个会话从0开始。当SET设置时,ADD添加一个金额。我想要一个函数来返回会话的最终值,例如

SELECT session_val(1); --returns 45 
SELECT session_val(2); --returns 55 

是否可以编写这样的函数/查询?我不知道如何用SQL做任何类似迭代的事情,或者如果可能的话。

+0

不应该'SELECT session_val(1);'return 35? – 2010-06-08 21:51:53

+0

@Ponies:记录会话= 1订单= 3在记录会话= 1订单= 2时加10。 – 2010-06-08 22:02:18

+0

如果会话没有“SET”会怎么样? – 2010-06-08 22:07:01

回答

6

那么,这是很难漂亮,但它的功能:

select sum(amt) as session_val 
from (
    select segment, 
     max(segment) over() as max_segment, 
     amt 
    from (
    select sum(case when atype = 'SET' then 1 else 0 end) 
       over(order by "order") as segment, 
      amt 
    from command 
    where session = 2 
) x 
) x 
where segment = max_segment 

这是虽然在PL/pgsql中很简单:

create function session_val(session int) returns int stable strict 
language plpgsql as $$ 
declare 
    value int := 0; 
    rec command%rowtype; 
begin 
    for rec in select * from command where command.session = session_val.session loop 
    if rec.atype = 'SET' then 
     value := rec.amt; 
    elsif rec.atype = 'ADD' then 
     value := value + rec.amt; 
    end if; 
    end loop; 
    return value; 
end $$; 

所以,你可以选择, 我猜。

+0

如果性能允许,我会做pl/pgsql,因为它的1000倍更清晰。 – rfusca 2010-06-09 03:15:29

1

要使用我的查询,您需要以SET 0记录开始每笔交易。此外,你将无法添加另一个类型,只有SETADD将按我的建议工作。

此查询未经测试。

的想法是简单地总结了最新的(最极致)SET,每ADD跟随其后:

SELECT SUM(amt) 
    WHERE session=X 
     AND order >= (SELECT MAX(order) 
         WHERE atype='SET' 
          AND session=X); 
+0

我不知道存储过程的语法,所以X是你的sproc参数。 – 2010-06-08 22:00:18

+0

+1:但是你可以关联而不是参考arg两次。 – 2010-06-08 22:05:40

+0

如果没有设置,它会做什么?它失败了吗?有没有在SQL中检查的方法? – Claudiu 2010-06-08 22:24:32