如何计算每个ID的正数和负数?

时间:2015-08-10 16:58:34

标签: sql oracle count window-functions

我希望得到每个ID的负值和正值的计数。

Sample Fiddle

ID=1 has 2 positive and 0 negative transactions. etc.

 with trans_detail as 
 (
 select 1 as trans_id, 100 as trans_amount  from dual union all
 select 1 as trans_id, 200 as trans_amount  from dual union all
 select 2 as trans_id, -100 as trans_amount  from dual union all
 select 2 as trans_id, -300 as trans_amount  from dual union all
 select 3 as trans_id, 400 as trans_amount   from dual union all
 select 3 as trans_id, -500 as trans_amount  from dual
 )

 select trans_id,
       count(*) over (partition by trans_id) as pos_count,
       count(*) over (partition by trans_id) as neg_count        
from trans_detail
where trans_amount > 0
UNION
select trans_id,
       count(*) over (partition by trans_id) as pos_count,
       count(*) over (partition by trans_id) as neg_count        
from trans_detail
where trans_amount < 0;

期望的结果:

 ID   POS_COUNT   NEG_COUNT
---- ----------- -----------
 1    2           0 
 2    0           2
 3    1           1

4 个答案:

答案 0 :(得分:4)

每次看到正数或负数时计数1并将其相加。

select trans_id,
sum(case when trans_amount >=0 then 1 else 0 end) as pos_amt,
sum(case when trans_amount < 0 then 1 else 0 end) as neg_amt
from trans_detail
group by trans_id

http://sqlfiddle.com/#!4/db410/12

答案 1 :(得分:1)

select trans_id, 
nvl(sum(case when trans_amount < 0 then 1 end),0) as neg,
nvl(sum(case when trans_amount > 0 then 1 end),0) as pos
from trans_detail
group by trans_id

SQL小提琴:http://sqlfiddle.com/#!4/db410/15

答案 2 :(得分:1)

您可以使用条件计数:

with trans_detail as 
 (
 select 1 as trans_id, 100 as trans_amount  from dual union all
 select 1 as trans_id, 200 as trans_amount  from dual union all
 select 2 as trans_id, -100 as trans_amount  from dual union all
 select 2 as trans_id, -300 as trans_amount  from dual union all
 select 3 as trans_id, 400 as trans_amount   from dual union all
 select 3 as trans_id, -500 as trans_amount  from dual
 )
select trans_id,
       count(case when trans_amount >= 0 then trans_id end) as pos_count,
       count(case when trans_amount < 0 then trans_id end) as neg_count        
from trans_detail
group by trans_id
order by trans_id;

  TRANS_ID  POS_COUNT  NEG_COUNT
---------- ---------- ----------
         1          2          0
         2          0          2
         3          1          1

Count忽略空值,因此每种情况的隐式null'else'表示不计算这些行。如果您愿意,可以添加else null,但只需要更长一点。 (我将零视为“正面”,但您可能希望完全忽略它,就像在您的问题中一样;在这种情况下,只需恢复为> 0)。

SQL Fiddle

您也可以在案例或解码中使用the sign function

select trans_id,
       count(decode(sign(trans_amount), 1, trans_id)) as pos_count,
       count(decode(sign(trans_amount), -1, trans_id)) as neg_count        
from trans_detail
group by trans_id
order by trans_id;

SQL Fiddle;这会忽略零,但如果你愿意,你可以将它包含在任何一个解码中。

答案 3 :(得分:1)

试试这个

select trans_id,
       Sum(case when trans_amount>=0 then 1 else 0 end) as pos_count,
       Sum(case when trans_amount<0 then 1 else 0 end) as neg_count,
from trans_detail
group by trans_id