6

I have a list of prices with decimals.

Example: 0.513 0.35135 1.6583

I'm trying to select the length of the decimal digits. Here's what I mean: 0.513 | length=3 0.35135 | length=5 1.6583 | length=4

I tried converting the numbers to text, but it doesn't seem to provide correct results: select price, length(cast(price as text)) from table.prices

I also tried this conversion method: "length(price::text)"

Any advice on how I can achieve this?

6 Answers 6

12

You can use the scale function, since postgresql 9.6 ;)

select scale(1.12345) as decimal_places;
 decimal_places 
----------------
              5
(1 row)

Sign up to request clarification or add additional context in comments.

2 Comments

If your data type is float you will get SQL Error [42883]: ERROR: function scale(double precision) does not exist. This would fix - select (scale(cast(your_col as numeric))) as decimal_places FROM your_table
scale(your_col::decimal) also works and is more succinct
3

This code works (see SQLFiddle Demo):

WITH test(x) AS (VALUES (0.513), (0.35135), (1.6583))
SELECT length((x - floor(x))::text)-2
FROM test

There is only one gotcha - for whole integers it returns -1.

3 Comments

Can you show counter-example? It works for any values I tried
My bad, I had forgotten to delete my comment.
If you have to ignore trailing zeroes (e.g. 0.12300) you can use SELECT length((x - floor(x::real))::text)-2
3

How about this:

CREATE FUNCTION decimal_places(n numeric) RETURNS int
LANGUAGE SQL IMMUTABLE
AS $$
select coalesce(length(substring(cast($1 as text) from '\..*$')) - 1, 0);
$$;

=> select decimal_places(0.513);
┌────────────────┐
│ decimal_places │
├────────────────┤
│              3 │
└────────────────┘

Comments

1
select double_value, length(split_part(double_value::text, '.', 2)) 
from your_table

To find how many decimal points, first convert double to text double_value::text, split text into two parts - the part before the decimal point and the part after the decimal point. Take the part after the decimal point split_part(double_value::text, '.', 2). Finally, get the length of the part after the decimal point.

1 Comment

While this code may answer the question, providing additional explanation will help (a) convince future readers to try your solution rather than one of the other existing answers, (b) increase the chances of your answer being helpful to others, and as a result (c) increase the chances of your answer being upvoted in the future. You can find more information in How do I write a good answer? - "Brevity is acceptable, but fuller explanations are better." It might be helpful to review some highly upvoted answers as examples to follow. Thanks!
0

Write an sql or plpgsql function for this. (Or better yet, do this in your app: it probably doesn't belong in Postgres to begin with.)

The pseudocode you need is:

  1. Cast the number to text.
  2. Find the dot position. If none, return zero, else compute the length accordingly.

If you're dealing with stuff that have exponents, make sure you cast the values to numeric first, so as to expand e.g. 1e-12 to 0.000000000001.

Comments

0

In select can be used like this:

SELECT length((SELECT regexp_matches(price::text,'(\\.\\d+)')::text)), price FROM table.prices

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.