Home > Net >  SQL: sum rows with conditions
SQL: sum rows with conditions

Time:04-11

I have a table in the database as follows:

date       account      side     size     
2022-01-01 1            buy      50
2022-01-01 1            sell     25
2022-01-01 1            buy      35
2022-01-01 1            sell     10
2022-01-01 2            buy      100
2022-01-01 2            sell     50
2022-01-02 1            buy      10
2022-01-02 1            sell     10
2022-01-02 2            buy      100
2022-01-02 2            sell     10

What I want is to subtract the size when the side is 'sell' and add it when it is buy to have something like this:

date       account      volume
2022-01-01 1            50
2022-01-01 2            50
2022-01-02 1            0  
2022-01-02 2            90

I have tried the following

select date, account, sum(case when size='sell' then size = -size else size = size end) as volume
group by date, account, side, size

But I get an error: ERROR: function sum(boolean) does not exist. HINT: No function matches the given name and argument types. You might need to add explicit type casts.

What am I doing wrong?

CodePudding user response:

Conditional aggregation is the way to go here, but your logic is a bit off. Also, you want to aggregate by only the date and account.

SELECT date, account,
       SUM(CASE WHEN size = 'buy' THEN size ELSE -size END) AS volume
FROM yourTable
GROUP BY date, account
ORDER BY date, account;

CodePudding user response:

Tim's answer is correct, and he addresses the multiple issues you have. I just want to expand on WHY you are getting the error you are getting with the sum/case combo so you can understand what you're doing wrong there.

SUM just tries to add up all the values, as its name suggests, and addition is really only valid with numeric values. You are actually lucky that you got the error message about the invalid Boolean values, because some languages would have just cast them to boolean integers (1 or 0) and summed that.

The issue is with your use of CASE.

sum(
  case 
    when size ='sell' then size = -size 
    else size = size 
  end
)

You are trying to use it to alter a value (you are trying to set the value of size to -size if the condition is met), but the CASE clause is actually going to return a value, whatever is after the then and else operators: in this case it will return either size = -size or size = size. In both cases you aren't return size or -size: you're returning the result of the comparison, either true or false, and then you are passing these Boolean values to SUM.

So what you want to do is make sure that the part after then or else matches your (and SUM's) expectations: a summable numeric value:

sum(
  case 
    when size ='sell' then -size 
    else size 
  end
)
  • Related