我需要使用PostgresSql.我得到下表称钱作为输入
Cash | Adhoc | Collateral | Total
---------------------------------
20 | 30 | 40 | 90
32 | 12 | 40 | 84
10 | 12 | 40 | 62
13 | 20 | 50 | 83
Run Code Online (Sandbox Code Playgroud)
顾名思义,总和是该行的现金,临时和抵押价值的总和.
我需要以下输出表
ChangeType | ChangeAmount
---------------------------
Cash | 12
Adhoc | -18
Cash | -22
Cash | 3
Adhoc | 8
Collateral | 10
Run Code Online (Sandbox Code Playgroud)
这是阶段1.在下一阶段,将添加一个名为clientId的新列,并为每个特定客户端显示这些更改.假设client1是第1行,客户端2是第2行和第3行,然后client1再次是第4行.然后将使用row1和row4形成client1的比较表.
输出表将是
ChangeType | ChangeAmount | ClientId
------------------------------------------
Cash | 7 | client1
Adhoc | -10 | client1
Collateral | 10 | client1
Cash | -22 | client2
Run Code Online (Sandbox Code Playgroud)
通过使用"行只有一列"在行之间切换时,我已经能够实现什么是chaging
SELECT
CASE WHEN ( (Cash - lag(Cash, 1)
OVER ( PARTITION BY clientId
) ) != 0)
THEN CAST('Cash' AS Text)
WHEN ( (Adhoc - lag(Adhoc, 1)
OVER ( PARTITION BY clientId
) ) != 0)
THEN CAST('Adhoc' AS Text)
WHEN ( (Collateral - lag(Collateral, 1)
OVER ( PARTITION BY clientId
) ) != 0)
THEN CAST('Collateral' AS Text)
END,
Total - lag(Total,1)
OVER ( PARTITION BY clientId )
FROM money
Run Code Online (Sandbox Code Playgroud)
然而,我失去了如何显示连续更改的多列的更改.
在某些情况下,过程方法比纯 SQL 容易得多。我认为是这样的。尝试下面的功能:
create or replace function show_money_changes()
returns table (change_type text, change_amount integer)
language plpgsql
as $$
declare
prev record;
curr record;
frst boolean = true;
begin
for curr in select * from money --order by id
loop
if not frst then
if curr.cash <> prev.cash then
return query select 'cash'::text, curr.cash - prev.cash;
end if;
if curr.adhoc <> prev.adhoc then
return query select 'adhoc'::text, curr.adhoc - prev.adhoc;
end if;
if curr.collateral <> prev.collateral then
return query select 'collateral'::text, curr.collateral - prev.collateral;
end if;
end if;
prev = curr;
frst = false;
end loop;
end $$;
select * from show_money_changes()
Run Code Online (Sandbox Code Playgroud)
注意:表中应该有一列(例如id)money来明确地对行进行排序。
纯SQL解决方案(假设表有id列且数字连续):
select * from (
select
unnest(array['cash', 'adhoc', 'collateral']) change_type,
unnest(array[m2.cash- m1.cash, m2.adhoc- m1.adhoc, m2.collateral- m1.collateral]) change_value
from money m1
join money m2 on m1.id+ 1 = m2.id
) alias
where change_value <> 0
Run Code Online (Sandbox Code Playgroud)
你必须改变条件
on m1.id+ 1 = m2.id
Run Code Online (Sandbox Code Playgroud)
(将当前行与下一行连接起来行连接)根据您的实际表定义。
您可以用于row_number()此目的。假设event_time是一个排序依据的列,那么:
with money_with_row_numbers as (
select *, row_number() over (order by event_time) rn
from money)
select * from (
select
unnest(array['cash', 'adhoc', 'collateral']) change_type,
unnest(array[m2.cash- m1.cash, m2.adhoc- m1.adhoc, m2.collateral- m1.collateral]) change_value
from money_with_row_numbers m1
join money_with_row_numbers m2 on m1.rn+ 1 = m2.rn
) alias
where change_value <> 0
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
73 次 |
| 最近记录: |