Question

I'm trying to divide two columns in the select statement, then round the quotient to 4 decimal places.

select round(round(sum(case when acct_no = '2999' 
      and date between '1/1/14' and current_date then amount end)::numeric, 4)::float
 / round(sum(case when acct_no = '3989' 
      and date between '1/1/14' and current_date then amount end)::numeric, 4)::numeric, 4) column
from table

The rest of the query will hold multiple dates, so the dates in there should be necessary.

The error it is giving:

ERROR: function round(double precision, integer) does not exist

This was attempted in PostgreSQL.

Was it helpful?

Solution 2

I re-formatted your example code to try and understand it more easily:

select  round(
            round(
                sum(
                    case
                        when    acct_no = '2999'
                                and date between '1/1/14' and current_date then amount
                    end )::numeric,
                4 )::float
            / round(
                sum(
                    case
                        when    acct_no = '3989'
                                and date between '1/1/14' and current_date then amount
                    end )::numeric,
                4 )::numeric,
            4 ) column
from table

The problem is that you're casting the numerator of your division operation as a float data type, which, because you didn't specify a precision, is equivalent to double precision.

round(
    sum(
        case
            when    acct_no = '2999'
                    and date between '1/1/14' and current_date then amount
        end )::numeric,
    4 )::float
/ round(
    sum(
        case
            when    acct_no = '3989'
                    and date between '1/1/14' and current_date then amount
        end )::numeric,
    4 )::numeric

So the result of the expression is a double precision value instead of as a numeric value, hence the error you observed.

OTHER TIPS

SELECT round((
          sum(CASE WHEN acct_no = '2999' 
              AND thedate between '2014-1-1' AND current_date THEN amount END)
        / sum(CASE WHEN acct_no = '3989' 
              AND thedate between '2014-1-1' AND current_date THEN amount END)
       )::numeric, 4) AS result
FROM   tbl;
  • There is no function round() with added precision modifier for floating point types in Postgres. Only for numeric, as per documentation.

  • Dividing a floating point number by numeric results in double precision (float8). Test:

      SELECT 5::float/3::numeric  -- result is double precision
    
  • Round once at the end of your calculation. That's faster and more accurate.

  • Never use date as column name. It's a reserved word in standard SQL and a base type in Postgres.

  • It's best to use the recommended ISO 8601 date format in date literals in your code. This works irregardless of settings and locale, while your local format would break with different settings.

If it wasn't for the rest of the query you mentioned, this could be simplified further:

SELECT round((   sum(CASE WHEN acct_no = '2999' THEN amount END)
        / NULLIF(sum(CASE WHEN acct_no = '3989' THEN amount END), 0)
       )::numeric, 4) AS result
FROM   tbl
WHERE  thedate between '2014-1-1'::date AND current_date;

Finally, this also catches "division by 0" exceptions using NULLIF() on the divisor.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top