PostgreSQL에서 평균을 소수점 이하 2 자리로 반올림하는 방법은 무엇입니까?


192

Ruby gem 'sequel'을 통해 PostgreSQL을 사용하고 있습니다.

소수점 이하 두 자리로 반올림하려고합니다.

내 코드는 다음과 같습니다.

SELECT ROUND(AVG(some_column),2)    
FROM table

다음과 같은 오류가 발생합니다.

PG::Error: ERROR:  function round(double precision, integer) does 
not exist (Sequel::DatabaseError)

다음 코드를 실행할 때 오류가 발생하지 않습니다.

SELECT ROUND(AVG(some_column))
FROM table

아무도 내가 뭘 잘못하고 있는지 알고 있습니까?


3
오류 메시지가 질문의 코드와 일치하지 않습니다.
mu는

구문 오류는 제외하고 dba.SE에서 밀접하게 관련된 질문 은 PostgreSQL에서 배정도 숫자를 반올림하는 데 약간의 도움이됩니다.
Erwin Brandstetter

@muistooshort, 지적 해 주셔서 감사합니다. 'avg'라고 표시된 곳에 'round'라고 표시해야합니다. 편집했습니다.
user1626730

결과 검색을 위해이 힌트를 프롬프트에서 출력으로 얻습니다.HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Vzzarr

답변:


266

PostgreSQL은 정의하지 않습니다 round(double precision, integer). 의견에서 @Mike Sherrill 'Cat Recall'이 설명하는 이유 때문에 정밀도를 취하는 라운드 버전은에서만 사용할 수 있습니다 numeric.

regress=> SELECT round( float8 '3.1415927', 2 );
ERROR:  function round(double precision, integer) does not exist

regress=> \df *round*
                           List of functions
   Schema   |  Name  | Result data type | Argument data types |  Type  
------------+--------+------------------+---------------------+--------
 pg_catalog | dround | double precision | double precision    | normal
 pg_catalog | round  | double precision | double precision    | normal
 pg_catalog | round  | numeric          | numeric             | normal
 pg_catalog | round  | numeric          | numeric, integer    | normal
(4 rows)

regress=> SELECT round( CAST(float8 '3.1415927' as numeric), 2);
 round 
-------
  3.14
(1 row)

위의 내용 float8은에 대한 축약 형 별칭입니다 double precision. PostgreSQL이 출력에서이를 확장하고 있음을 알 수 있습니다.

numeric두 인수 형식의를 사용하려면 반올림 할 값을 캐스트해야합니다 round. 다음 ::numeric과 같이 속기 캐스팅을 추가하십시오 round(val::numeric,2).


사용자에게 표시 할 형식을 지정하는 경우을 사용하지 마십시오 round. 사용 to_char(참조 : 데이터 유형 포맷 함수 매뉴얼에), 당신은 형식을 지정할 수 있습니다 당신에게주는 text함께 할 수있는 클라이언트 언어 불확실성 어떤 영향을받지 않는 결과 numeric값을. 예를 들면 다음과 같습니다.

regress=> SELECT to_char(float8 '3.1415927', 'FM999999999.00');
    to_char    
---------------
 3.14
(1 row)

to_char서식의 일부로 숫자를 반올림합니다. FM접두사는 이야기 to_char는 선행 공백과 패딩을 싶지 않아.


흠. 시도 ROUND(CAST(FLOAT8 '3.1415927' AS NUMERIC),2);하면 '0.314E1'이 나타납니다. 그리고 내 코드는 다음과 같이 작성되었습니다.ROUND(AVG(val),2) 했지만 여전히 내 질문에 설명 된 오류가 발생합니다.
user1626730

방금 ROUND(CAST(FLOAT8 '3.1415927' AS NUMERIC),2);PgAdmin과 Ruby에서 실행 했습니다. PgAdmin을 사용하면 3.14를 얻지 만 Ruby (Sequel gem 사용)를 사용하면 '0.314E1'을 얻습니다. 나는이 ... 왜 궁금해
user1626730가

12
"어떤 이상한 이유로 정밀도를 취하는 라운드 버전은 숫자로만 사용할 수 있습니다." 부동 소수점 숫자는 "유용한 근사치"입니다. 부동 소수점 숫자를 소수점 이하 두 자리로 반올림하여 다른 부동 소수점 숫자를 반환하도록 코드에 요청 하면 "오른쪽"답변에 가장 가까운 근사값이 소수점 오른쪽에 두 자리 만 있다고 보장 할 수 없습니다. 숫자는 효과적으로 스케일링 된 정수입니다. 그들은 그 문제가 없습니다.
Mike Sherrill 'Cat

@Catcall 좋은 점-의 double버전은 또는 (ugh) round를 반환해야 하므로 인수를 취할 수도 있습니다 . numerictextnumeric
Craig Ringer

6
@Catcall로 의견을 찾으려고 사람들을 위해 : 지금은 마이크 Sherrill '고양이 리콜'
18,446,744,073,709,551,615

89

캐스팅에 대한 이전 구문을 사용해보십시오.

SELECT ROUND(AVG(some_column)::numeric,2)    
FROM table;

PostgreSQL의 모든 버전에서 작동합니다.

일부 PostgreSQL 함수 에는 오버로드가 부족한 이유는 무엇입니까? 왜?

추신 : 반올림에 대한 또 다른 요점은 정확성 입니다. @ IanKenney 's answer 확인하십시오 .


캐스팅 전략으로서의 과부하

다음 과 같이 ROUND 기능을 과부하 시킬 수 있습니다 .

 CREATE FUNCTION ROUND(float,int) RETURNS NUMERIC AS $$
    SELECT ROUND($1::numeric,$2);
 $$ language SQL IMMUTABLE;

이제 명령이 제대로 작동합니다 (함수 생성 후)

 SELECT round(1/3.,4); -- 0.3333 numeric

하지만 NUMERIC 유형을 반환합니다. 첫 번째 commom-usage 과부하를 유지하기 위해 TEXT 매개 변수가 제공 될 때 FLOAT 유형을 반환 할 수 있습니다.

 CREATE FUNCTION ROUND(float, text, int DEFAULT 0) 
 RETURNS FLOAT AS $$
    SELECT CASE WHEN $2='dec'
                THEN ROUND($1::numeric,$3)::float
                -- ... WHEN $2='hex' THEN ... WHEN $2='bin' THEN... complete!
                ELSE 'NaN'::float  -- like an error message 
            END;
 $$ language SQL IMMUTABLE;

시험

 SELECT round(1/3.,'dec',4);   -- 0.3333 float!
 SELECT round(2.8+1/3.,'dec',1); -- 3.1 float!
 SELECT round(2.8+1/3.,'dec'::text); -- need to cast string? pg bug 

추신 : \df round과부하 후 점검 하면 다음과 같이 표시됩니다.

스키마 | 이름 | 결과 데이터 유형 | 인수 데이터 유형
------------ + ------- + ------------------ + ---------- ------------------
 미스 테마 | 라운드 | 배정도 | 배정도, 텍스트, int
 미스 테마 | 라운드 | 숫자 | 배정도, int
 pg_catalog | 라운드 | 배정도 | 배정도            
 pg_catalog | 라운드 | 숫자 | 숫자   
 pg_catalog | 라운드 | 숫자 | 숫자, 정수          

pg_catalog기능은 기본 것들 볼 빌드 - 수학 함수의 매뉴얼 .


38

이것으로 시도하십시오 :

SELECT to_char (2/3::float, 'FM999999990.00');
-- RESULT: 0.67

또는 간단히 :

SELECT round (2/3::DECIMAL, 2)::TEXT
-- RESULT: 0.67

5
나는 이것이이 질문에 대한 나의 대답으로 훨씬 간결하고 해로운 진전임을 알았습니다. : bow :
craastad

2
여기 동일합니다! 매우 짧고 유용한 솔루션입니다.
Alexey Shabramov

7

아래 기능을 사용할 수 있습니다

 SELECT TRUNC(14.568,2);

결과는 다음과 같이 표시됩니다.

14.56

변수를 원하는 유형으로 캐스트 할 수도 있습니다.

 SELECT TRUNC(YOUR_VAR::numeric,2)

3

Bryan의 응답 에 따르면 쿼리에서 소수를 제한하기 위해이 작업을 수행 할 수 있습니다. km / h에서 m / s로 변환하여 dygraphs에 표시하지만 dygraph에서 수행했을 때 이상하게 보였습니다. 대신 쿼리에서 계산을 수행 할 때 잘 보입니다. 이것은 postgresql 9.5.1에 ​​있습니다.

select date,(wind_speed/3.6)::numeric(7,1) from readings;


1

오류 : 함수 반올림 (배정 밀도, 정수)이 존재하지 않습니다

해결책 : 타입 캐스트를 추가해야 작동합니다.

전의: round(extract(second from job_end_time_t)::integer,0)


0

total_amount FROM 트랜잭션으로 ROUND (SUM (amount) :: numeric, 2)를 선택하십시오.

제공 : 200234.08

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.