PostgreSQL'de ortalama 2 ondalık basamağa nasıl yuvarlanır?


192

Ruby Gem 'devamı' üzerinden PostgreSQL kullanıyorum.

İki ondalık basamağa yuvarlanmaya çalışıyorum.

İşte benim kod:

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

Aşağıdaki hatayı alıyorum:

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

Aşağıdaki kodu çalıştırdığınızda hata alıyorum:

SELECT ROUND(AVG(some_column))
FROM table

Ne yaptığımı bilen var mı?


3
Hata mesajınız, sorunuzdaki kodla eşleşmiyor.
mu çok kısa

Sözdizimi hatası bir yana, dba.SE ile yakından ilgili bu soru PostgreSQL'de çift kesinlikli sayıların yuvarlanmasına biraz ışık tutuyor.
Erwin Brandstetter

@muistooshort, Bunu gösterdiğin için teşekkürler. 'Avg' dediği yerde 'yuvarlak' yazmalıdır. Düzenlenen.
user1626730

arama sonuçları uğruna, ben de isteminden çıktı olarak bu ipucu olsun:HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Vzzarr

Yanıtlar:


266

PostgreSQL tanımlamaz round(double precision, integer). @Mike Sherrill'in 'Cat Recall' açıklamalarında açıkladığı nedenlerden ötürü, kesinlik kazandıran raund versiyonu sadece için geçerlidir 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)

(Yukarıda, bunun float8sadece kestirme bir takma ad olduğuna dikkat edin double precision. PostgreSQL'in çıktıda genişlediğini görebilirsiniz).

Öğesinin numericiki bağımsız değişken biçimini kullanmak için yuvarlanacak değeri kullanmalısınız round. Sadece ::numericsteno kast için ekleyin round(val::numeric,2).


Kullanıcıya görüntüleme için biçimlendiriyorsanız kullanmayın round. Bir biçim belirtmenize olanak tanıyan ve istemci dilinizin değerlerle ilgili tuhaflıklarından etkilenmeyen bir sonuç veren to_char( kullanım kılavuzundaki veri türü biçimlendirme işlevleri ) konusuna bakın . Örneğin:textnumeric

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

to_charbiçimlendirmenin bir parçası olarak sizin için sayıları yuvarlar. FMÖneki söyler to_charEğer lider boşluk içeren herhangi bir dolgu istemiyorum.


Hmm. Denediğimde ROUND(CAST(FLOAT8 '3.1415927' AS NUMERIC),2);, '0.314E1' alıyorum. Ve kodumu ROUND(AVG(val),2)hala yazdım hala sorumu açıkladığım hatayı aldım.
user1626730

Sadece ROUND(CAST(FLOAT8 '3.1415927' AS NUMERIC),2);PgAdmin ve Ruby'de koştum . PgAdmin ile 3.14 elde ediyorum, ama Ruby ile (Sequel gem kullanarak) '0.314E1' alıyorum. Bunun neden olduğunu merak ediyorum ...
user1626730 28:12

12
"Tuhaf bir nedenden ötürü, kesinlik gerektiren raund sürümü yalnızca sayısal olarak kullanılabilir." Kayan nokta sayıları "yararlı yaklaşımlardır". Koddan kayan noktalı bir sayıyı iki ondalık basamağa yuvarlamasını ve başka bir kayan noktalı sayı döndürmesini isterseniz, "sağ" yanıta en yakın yaklaşımın ondalık sayının sağında yalnızca iki basamak olacağını garanti etmez. Sayısallar etkili bir şekilde ölçeklenmiş tamsayılardır; bu problemleri yok.
Mike Sherrill 'Cat Recall'

@Catcall İyi bir nokta - bir doubleversiyonunun roundgeri dönmesi numericya da (ugh) olması gerekir text, bu yüzden bir numericargüman alabilir .
Craig Ringer

6
@Catcall tarafından yorumu bulmaya çalışanlar için: şimdi Mike Sherrill 'Cat Recall'
18446744073709551615 7:16

89

Ayrıca döküm için eski sözdizimini deneyin,

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

PostgreSQL'in herhangi bir sürümü ile çalışır.

Bazı PostgreSQL fonksiyonlarında aşırı yüklenme eksikliği var , neden (???): Bence "bir eksikliktir" (!), Ancak @CraigRinger, @Catcall ve PostgreSQL ekibi "pg'nin tarihi mantığı" konusunda hemfikir.

Not: Yuvarlama ile ilgili bir başka nokta doğruluktur , @ IanKenney'in cevabını kontrol edin .


Döküm stratejisi olarak aşırı yükleme

YUVARLA işlevini aşırı yükleyebilirsiniz ,

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

Şimdi talimatınız iyi çalışır, deneyin (işlev oluşturulduktan sonra)

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

ancak bir NUMERIC türü döndürür ... İlk commom kullanım aşırı yüklenmesini korumak için, bir TEXT parametresi sunulduğunda bir FLOAT türü döndürebiliriz,

 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;

Deneyin

 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 

Not: \df roundAşırı yüklemelerden sonra kontrol etmek ,

Şeması | İsim | Sonuç veri türü | Bağımsız değişken veri türleri
------------ + ------- + ------------------ + ---------- ------------------
 myschema | yuvarlak | çift ​​kesinlik | çift ​​kesinlik, metin, int
 myschema | yuvarlak | sayısal | çift ​​kesinlik, int
 pg_catalog | yuvarlak | çift ​​kesinlik | çift ​​hassasiyet            
 pg_catalog | yuvarlak | sayısal | sayısal   
 pg_catalog | yuvarlak | sayısal | sayısal, int          

pg_catalogFonksiyonlar, varsayılan olanlardır bkz kurarak küçük bir matematik fonksiyonlarının manuel .


38

Şunu deneyin:

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

Ya da sadece:

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

5
Ben bu soruya benim gün cevap ile çok daha özlü ve boğazı ileri hareket olarak buluyorum. : yay:
craastad

2
Burada aynı! Çok kısa ve kullanışlı bir çözüm.
Alexey Shabramov

7

aşağıdaki işlevi kullanabilirsiniz

 SELECT TRUNC(14.568,2);

sonuç şunu gösterecektir:

14.56

değişkeninizi arzu türüne de ekleyebilirsiniz:

 SELECT TRUNC(YOUR_VAR::numeric,2)

3

Bryan'ın yanıtına göre , bunu bir sorgudaki ondalık sayıları sınırlamak için yapabilirsiniz. Km / s'den m / s'ye dönüştürür ve çizimlerde görüntülerim, ancak çizimlerde yaptığımda garip görünüyordu. Bunun yerine sorguda hesaplama yaparken iyi görünüyor. Bu postgresql 9.5.1 üzerindedir.

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

2

Sütununuzu aşağıdaki gibi bir sayısal değere yayınlamayı deneyin:

SELECT ROUND(cast(some_column as numeric),2) FROM table

1

Hata: fonksiyon yuvarlak (çift kesinlik, tamsayı) mevcut değil

Çözüm : Cast tipi eklemeniz gerekiyor, o zaman işe yarayacak

Ör: round(extract(second from job_end_time_t)::integer,0)


0

total_amount FROM işlemi olarak ROUND (SUM (miktar) :: sayısal, 2) öğesini seçin

verir: 200234.08

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.