จะปัดเศษทศนิยมเฉลี่ย 2 ตำแหน่งใน PostgreSQL ได้อย่างไร


192

ฉันใช้ PostgreSQL ผ่าน Ruby gem 'sequel'

ฉันพยายามปัดทศนิยมสองตำแหน่ง

นี่คือรหัสของฉัน:

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 ขอบคุณสำหรับการชี้ให้เห็น มันควรจะพูดว่า 'round' ซึ่งมันบอกว่า 'avg' แก้ไข
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เพียงแค่ต่อท้ายสำหรับหล่อชวเลขเช่น::numericround(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 Recall'

@Catcall Good point - doubleเวอร์ชันของroundต้องส่งคืนnumericหรือ (ugh) textดังนั้นอาจใช้numericอาร์กิวเมนต์
Craig Ringer

6
สำหรับผู้ที่พยายามค้นหาความคิดเห็นโดย @Catcall: ตอนนี้มันคือMike Sherrill 'Cat Recall'
18446744073709551615

89

ลองใช้ไวยากรณ์เก่าเพื่อการคัดเลือก

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

ทำงานร่วมกับ PostgreSQL รุ่นใดก็ได้

มีการขาดเกินพิกัดในบางฟังก์ชันของ PostgreSQL ทำไม (???): ฉันคิดว่า "มันคือการขาด" (!) แต่ @CraigRinger, @Catcall และทีม PostgreSQL เห็นด้วยกับเหตุผลของประวัติศาสตร์ของ pg "

PS: ประเด็นเกี่ยวกับการปัดเศษอีกอย่างก็คือความถูกต้องตรวจสอบ@ คำตอบของ


มากไปเป็นกลยุทธ์การคัดเลือกนักแสดง

คุณสามารถโอเวอร์โหลดฟังก์ชัน 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 ... เพื่อรักษาปริมาณการใช้เกินคอมมิชชันแรกเราสามารถคืนค่าชนิด FLOAT เมื่อมีการเสนอพารามิเตอร์ TEXT

 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 

PS: การตรวจสอบ\df roundหลังจากการบรรทุกเกินพิกัดจะแสดงสิ่งที่ต้องการ

สคีมา ชื่อ | ประเภทข้อมูลผลลัพธ์ | ชนิดข้อมูลอาร์กิวเมนต์
------------ + ------- + + ------------------ ---------- ------------------
 myschema ปัดเศษ ความแม่นยำสองเท่า ความแม่นยำสองเท่า, ข้อความ, int
 myschema ปัดเศษ ตัวเลข | ความแม่นยำสองเท่า int
 pg_catalog | ปัดเศษ ความแม่นยำสองเท่า ความแม่นยำสองเท่า            
 pg_catalog | ปัดเศษ ตัวเลข | เป็นตัวเลข   
 pg_catalog | ปัดเศษ ตัวเลข | ตัวเลข, int          

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

ตามการตอบสนองของไบรอันคุณสามารถทำได้เพื่อ จำกัด ทศนิยมในแบบสอบถาม ฉันแปลงจาก km / h เป็น m / s และแสดงเป็น dygraphs แต่เมื่อฉันทำใน dygraphs มันดูแปลก ๆ ดูดีเมื่อทำการคำนวณในแบบสอบถามแทน นี่คือบน postgresql 9.5.1

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


1

ข้อผิดพลาด: ไม่มีฟังก์ชันกลม (ความแม่นยำสองเท่า, จำนวนเต็ม)

วิธีแก้ปัญหา : คุณต้อง addtype cast แล้วมันจะทำงาน

Ex: round(extract(second from job_end_time_t)::integer,0)


0

เลือก ROUND (SUM (จำนวน) :: ตัวเลข 2) เป็นจำนวนเงินทั้งหมดจากการทำธุรกรรม

ให้: 200234.08

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.