Question

I'm trying to get the quotient of two columns inside the select statement. Here's what I have tried.

Select ( select sum(x.amount) amount
         from this_table x
         where x.acct_no = '52'
       ) / 
       ( select sum(x.amount) amount
         from this_table x
         where x.acct_no = '53'
       ) as amount
from this_table y
join this_table x on x.acct_no = y.acct_no
where x.acct_no = '52' or x.acct_no = '53'

When I do this, my amount column just comes out as 1, and I'm positive that isn't what the result should be. Any advice or help? Solution?

Was it helpful?

Solution

This should do as you want:

select  sum(case when acct_no = '52' then amount else 0 end)
      / sum(case when acct_no = '53' then amount else 0 end) as amount
from    this_table
where   acct_no in ('52','53')

To make the amount column show zero if the divisor is zero (rather than return an error), you can use:

select  case when sum(case when acct_no = '53' then amount else 0 end) = 0 then 0
        else
        sum(case when acct_no = '52' then amount else 0 end)
      / sum(case when acct_no = '53' then amount else 0 end) end as amount
from    this_table
where   acct_no in ('52','53')

May be useful if you plan on doing this often and/or using the results in an application where you don't want an error thrown back at you.

OTHER TIPS

Cast to numeric

select 3 / 2;
 ?column? 
----------
        1

select 3::numeric / 2;
      ?column?      
--------------------
 1.5000000000000000

This ought to do you:

select ratio = sum(cast( case t.acct_no when '52' then t.amount else 0.00 end as numeric(15,2) )
             / sum(cast( case t.acct-no when '53' then t.amount else 0.00 end as numeric(15,2) )
from this_table t
where t.acct_no in ( '52' , '53' )

You might not need the cast if amount is a suitable data type.

The basic statement would be:

SELECT 
  (SELECT sum(amount)::numeric   FROM this_table WHERE acct_no = '52')  /
  (SELECT NULLIF(sum(amount), 0) FROM this_table WHERE acct_no = '53') AS div
  • NULLIF prevents division by 0. You get NULL in this case, which is the appropriate result.

  • If amount is some kind of integer, cast to a numeric type with more precision to preserve fractional digits. (You may want round().) One cast is enough, the result is in the data-type with the greater precision. Relevance dependings on your actual types.

  • A single query with CASE statements like @Brian provided may be faster. With an index it hardly matters.

  • Am index on (acct_no) makes this fast, a multicolumn index on (acct_no, amount) even faster, if index-only scans (Postgres 9.2+) are possible.

FWIW I just had a play in SQLFiddle http://sqlfiddle.com/#!1/d41d8/1606 , and if you're only after a single row single column result, PostgreSQL seems to allow :

WITH Amounts52 as (select   23 as sum52),
     Amounts53 as (select 4356 as sum53)
SELECT Amounts52.sum52::float
     / Amounts53.sum53  AS Result
FROM Amounts52, Amounts53

So you can put your Sum() queries in the two Common Table Expressions and get a the single result - if this approach appeals to you (it has its uses)

Of course it is a lot simpler to use this ( http://sqlfiddle.com/#!1/d41d8/1924/0 ) :

SELECT (select   23 as sum52)
      /(select 4356 as sum53)::float AS Answer
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top