2016-12-19 30 views
0

我有一个类似下面的例子的表,其中包含日期,数量,借方,贷方和余额(借方值+ 0 - 贷记值),所以我想选择记录相同的数字和余额总和等于0,然后识别这些记录。确定余额等于零的记录

我试图创建一个函数,但我只在有两个相同的记录。在这个例子中,它是219900。在其他情况下,我不能。

我想在别人的记录中,这是**之间。

date  num  debit credit  balance zero_balance 
11/11/2016 219900   470,00  -470,00  Y 
11/11/2016 219900 470,00    470,00  Y 

01/11/2016 218295 163,00    163,00  
30/11/2016 218295 162,00    162,00  **Y** 
30/11/2016 218295 162,00    162,00  **Y** 
30/11/2016 218295   162,00  -162,00  **Y** 
30/11/2016 218295   162,00  -162,00  **Y** 
30/11/2016 218295 162,00    162,00 

25/10/2016 218102 935,46    935,46  **Y** 
25/10/2016 218102   935,46  -935,46  **Y** 
25/10/2016 218102 935,46    935,46 

20/10/2016 217638 1.896,65   1.896,65 **Y** 
20/10/2016 217638   1.896,65 -1.896,65 **Y** 
20/10/2016 217638 1.896,65   1.896,65 **Y** 
20/10/2016 217638   1.896,65 -1.896,65 **Y** 
20/10/2016 217638 1.696,65   1.696,65  

有人可以帮我吗?

+0

那么,你感兴趣的只是对(其中余额为零,而一个行只能是一对)? – pozs

+0

@pozs是的,当有记录存在你的对立面时,一个会使另一个记录无效,因为我需要将其导出并仅显示已打开的信用点或借方。 – thiagofred

+0

你在这个表中有主键吗? (它通常是最好的所有表让他们在你的情况下,它是一个要求:没有它,你不能确保记录将只在一个对使用) – pozs

回答

1

我会打电话给你的表t(在查询中使用自己的名字)。另外,我根本不会使用balance字段;它似乎是多余的(但答案也可用于该列)。

如果你有一个主键,你就必须给每个num的贷方和借方指数(cd_idx下文)。您可以使用该索引搜索配对。

with d as (
    select t r, row_number() over (partition by num, credit, debit order by date, id) cd_idx 
    from t 
) 
select (d1.r).*, (d2.r).id is not null zero_balance 
from  d d1 
left join d d2 on (d1.r).id <> (d2.r).id 
and  (d1.r).num = (d2.r).num 
and  d1.cd_idx = d2.cd_idx 
and  ((d1.r).credit = (d2.r).debit or (d1.r).debit = (d2.r).credit) 
order by (d1.r).id 

注意,对于以升序相同num, credit, debit元组由date, id生成cd_idx。还要注意,我把整个行到r列,但你没有,如果你想只选择特定的列(这样我可以很容易地选择所有属性该行的(d1.r).*)。

如果您没有主键,则可以使用row_number()临时生成一个,但这样您不能保证获得多次执行的相同结果。

with t as (select *, row_number() over() id from t), 
d as (
    select t r, row_number() over (partition by num, credit, debit order by date, id) cd_idx 
    from t 
) 
select (d1.r).*, (d2.r).id is not null zero_balance 
from  d d1 
left join d d2 on (d1.r).id <> (d2.r).id 
and  (d1.r).num = (d2.r).num 
and  d1.cd_idx = d2.cd_idx 
and  ((d1.r).credit = (d2.r).debit or (d1.r).debit = (d2.r).credit) 
order by (d1.r).id 

Rextester

+0

我认为它像我想要的那样工作。但我忘记了一种情况:有一种情况是有一笔贷记录和两笔以上的借记记录,反之亦然,但余额总和等于零。我会用这个,我会尝试调整另一种方式。谢谢! – thiagofred

+0

@thiagofred不幸的是,这种情况并不容易。如果存在多个有效配对,则需要执行类似[backtracking](https://en.wikipedia.org/wiki/Backtracking)的操作,因为可能存在'C1 = D1 + D2'的合法候选人, C2 = D3 + D4 + D5',但是“正常”搜索可能会首先找到“C1 = D6 + D2 + D5”,然后因为C2≠D1 + D3 + D4而无法再找到它 – pozs

+0

我做了查询并将它们保存在另一张桌子上。之后,我做了一个函数,选择零余额=假的行,并做了一个函数来比较借贷金额和贷项金额,当这个结果相等时,我将零余额设置为true。 我认为这不是最正确或有效的方式,但目前它正在工作。 – thiagofred

0

使用窗口功能 https://www.postgresql.org/docs/current/static/tutorial-window.html 我认为它应该帮助你。

select 
    date 
    ,num 
    ,debit 
    ,credit 
    ,sum(debit) over (partition by num) as sum_deb 
    ,sum(credit) over (partition by num) as sum_cred 
    ,case when 
     sum(debit) over (partition by num) = sum(credit) over (partition by num) 
     then 'Y' else 'N' end as zero_balance 
from test_debt 
+0

这是一个很好的帮助,但它还不是我所需要的。我没有正确解释,但是当我需要一个记录是相反的值时,两者都应该被识别。因为有7个记录具有相同的数字,但至少有一个不是你的对立面,只是这不会被识别。 – thiagofred