Làm cách nào để làm tròn trung bình đến 2 chữ số thập phân trong PostgreSQL?


191

Tôi đang sử dụng PostgreSQL thông qua 'phần tiếp theo' của Ruby gem.

Tôi đang cố gắng làm tròn đến hai chữ số thập phân.

Đây là mã của tôi:

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

Tôi nhận được lỗi sau đây:

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

Tôi không gặp lỗi khi chạy đoạn mã sau:

SELECT ROUND(AVG(some_column))
FROM table

Có ai biết tôi đang làm gì sai không?


3
Thông báo lỗi của bạn không khớp với mã trong câu hỏi của bạn.
mu quá ngắn

Lỗi cú pháp sang một bên, câu hỏi liên quan chặt chẽ này trên dba.SE làm sáng tỏ về làm tròn số chính xác gấp đôi trong PostgreQuery.
Erwin Brandstetter

@muistooshort, Cảm ơn bạn đã chỉ ra điều đó. Nó sẽ nói 'vòng' trong đó nó nói 'avg'. Đã chỉnh sửa.
dùng1626730

để tìm kiếm kết quả vì lợi ích, tôi cũng nhận được gợi ý này dưới dạng đầu ra từ dấu nhắc:HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Vzzarr

Câu trả lời:


264

PostgreSQL không định nghĩa round(double precision, integer). Vì lý do @Mike Sherrill 'Cat Recall' giải thích trong các bình luận, phiên bản của vòng có độ chính xác chỉ có sẵn cho 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)

(Trong phần trên, lưu ý rằng đó float8chỉ là một bí danh tốc ký cho double precision. Bạn có thể thấy PostgreQuery đang mở rộng nó trong đầu ra).

Bạn phải truyền giá trị được làm tròn numericđể sử dụng dạng hai đối số của round. Chỉ cần thêm ::numericcho các diễn viên tốc ký, như round(val::numeric,2).


Nếu bạn định dạng để hiển thị cho người dùng, đừng sử dụng round. Sử dụng to_char(xem: chức năng định dạng kiểu dữ liệu trong hướng dẫn sử dụng), cho phép bạn chỉ định một định dạng và cung cấp cho bạn một textkết quả không bị ảnh hưởng bởi bất kỳ sự kỳ lạ nào mà ngôn ngữ khách hàng của bạn có thể làm với numericcác giá trị. Ví dụ:

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

to_charsẽ làm tròn số cho bạn như là một phần của định dạng. Các FMtiền tố nói to_charrằng bạn không muốn bất kỳ đệm với không gian hàng đầu.


Hừm. Khi tôi thử ROUND(CAST(FLOAT8 '3.1415927' AS NUMERIC),2);, tôi nhận được '0.314E1'. Và tôi có mã của tôi được viết như ROUND(AVG(val),2)vẫn nhận được lỗi tôi mô tả trong câu hỏi của tôi.
dùng1626730

Tôi chỉ chạy ROUND(CAST(FLOAT8 '3.1415927' AS NUMERIC),2);trên PGAdmin và Ruby. Với PGAdmin, tôi nhận được 3.14, nhưng với Ruby (sử dụng đá quý Sequel), tôi nhận được '0.314E1'. Tôi tự hỏi tại sao đây là ...
user1626730

12
"Vì một số lý do kỳ lạ, phiên bản của vòng có độ chính xác chỉ có sẵn cho số." Số dấu phẩy động là "xấp xỉ hữu ích". Nếu bạn yêu cầu mã làm tròn số dấu phẩy động thành hai chữ số thập phân, trả về một số dấu phẩy động khác , không có gì đảm bảo rằng phép gần đúng nhất với câu trả lời "đúng" sẽ chỉ có hai chữ số ở bên phải số thập phân. Số là các số nguyên có hiệu quả; họ không có vấn đề đó
Mike Sherrill 'Nhớ lại mèo'

@Catcall Điểm hay - một doublephiên bản roundsẽ cần phải trả lại numerichoặc (ugh) text, vì vậy nó cũng có thể đưa ra một numericđối số.
Craig Ringer

6
Đối với những người đang cố gắng tìm bình luận của @Catcall: bây giờ nó là Mike Sherrill 'Cat Recall'
18446744073709551615

88

Hãy thử cú pháp cũ để truyền,

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

hoạt động với bất kỳ phiên bản nào của PostgreSQL.

Thiếu một số chức năng quá tải trong một số chức năng của PostgreSQL, tại sao (???): Tôi nghĩ rằng "đó là thiếu" (!), Nhưng @CraigRinger, @Catcall và nhóm PostgreQuery đồng ý về "lý do lịch sử của pg".

PS: một điểm khác về làm tròn là độ chính xác , hãy kiểm tra câu trả lời của @ IanKenney .


Quá tải như chiến lược đúc

Bạn có thể quá tải hàm ROUND với,

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

Bây giờ hướng dẫn của bạn sẽ hoạt động tốt, hãy thử (sau khi tạo chức năng)

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

nhưng nó trả về một kiểu SỐ ... Để duy trì tình trạng quá tải sử dụng dấu phẩy đầu tiên, chúng ta có thể trả về loại FLOAT khi tham số TEXT được cung cấp,

 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;

Thử

 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 

PS: kiểm tra \df roundsau khi quá tải, sẽ hiển thị một cái gì đó như,

Lược đồ | Tên | Kiểu dữ liệu kết quả | Các kiểu dữ liệu đối số
------------ + ------- + ------------------ + ---------- ------------------
 myschema | vòng | độ chính xác kép | độ chính xác kép, văn bản, int
 myschema | vòng | số | độ chính xác kép, int
 pg_catalog | vòng | độ chính xác kép | độ chính xác kép            
 pg_catalog | vòng | số | số   
 pg_catalog | vòng | số | số, int          

Các pg_cataloghàm là mặc định, xem hướng dẫn sử dụng các hàm toán học tích hợp .


38

Hãy thử với điều này:

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

Hoặc đơn giản:

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

5
Tôi thấy đây là một bước tiến ngắn gọn và tiến bộ hơn với câu trả lời hàng ngày của tôi cho câu hỏi này. : cúi đầu:
craastad

2
Tương tự ở đây! Giải pháp rất ngắn gọn và hữu ích.
Alexey Shabramov

7

bạn có thể sử dụng chức năng dưới đây

 SELECT TRUNC(14.568,2);

kết quả sẽ hiển thị:

14.56

bạn cũng có thể chuyển biến của mình sang loại mong muốn:

 SELECT TRUNC(YOUR_VAR::numeric,2)

3

Theo phản hồi của Bryan, bạn có thể làm điều này để hạn chế số thập phân trong truy vấn. Tôi chuyển đổi từ km / h sang m / s và hiển thị nó trong máy in nhưng khi tôi thực hiện nó trong máy in thì nó trông thật kỳ lạ. Có vẻ tốt khi thực hiện tính toán trong truy vấn thay thế. Đây là trên postgresql 9.5.1.

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


1

Lỗi: vòng chức năng (độ chính xác kép, số nguyên) không tồn tại

Giải pháp : Bạn cần thêm casttype thì nó sẽ hoạt động

Ví dụ: round(extract(second from job_end_time_t)::integer,0)


0

chọn ROUND (SUM (số tiền) :: số, 2) làm tổng số giao dịch TỪ

cho: 200234,08

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.