xom`s pinion - xomův blog

Blog šťastného středoevropana plný subjektivních blábolů.

Dejchá, furt dejchá!
Větvička
úvod » PostgreSQL, funkce round() a 666

PostgreSQL, funkce round() a 666

PostgreSQL To mě zase jednou sloník PgSQL pěkně převezl.. Program automatizace přiřazování plateb k fakturám pracoval bezproblémově, než došlo na fakturu s částkou 666 bez DPH, což je s 19% daní 792,54. Funkce vyvolaná triggerem na insert platbu nespárovala.. Kde je chyba?

Ceny s DPH zaokrouhluji klasickým způsobem, tedy na celá čísla k nejbližší hodnotě (72,5 je 73 apod.) a právě při zaokrouhlení došlo k problému.

round(SUM(price*(tax+100)/100)) INTO not_paid
První ukázka

Jakou myslíte, že bude mít proměnná not_paid hodnotu, pokud je price=666 a tax=19? 792, ale proč? Pokud rozšíříme zaokrouhlení na dvě desetinná místa, tak dostaneme odpovědi 792,00, takže musí docházet k zaokrouhlení již někde dříve.. Myslel jsem, že při tom dělení stem, ale nakonec se ukázalo, že při tom násobení (samozřejmě, že ne, že to zapříčiňuje dělení), proto stačí doplnit definici numeric(v,s), přičemž v definuje počet číslic v čísle a s přesnost desetinných míst. Doplněno: Nebo, jak psal Andrew v komentářích, nepřetypovávat a jedno z čísel, např. 100 napsat desetinně a výsledek bude s desetinnou čárkou.

round(SUM(price*(tax+100)::numeric(10,2)/100)) INTO not_paid
Druhá ukázka

Pro mé účely jsem použil výše zmíněnou syntaxi a vše již běhá v pořádku a aspoň vím, že si někdy dokáže Postgre leccos domyslet a převést, bohužel v tomto případě na integer..

Aktualizováno:
Ani si nikdo nevšiml, že nadpis článku proklamoval funkci rand, přitom byl text o round, adresu spotu nechávám starou, je již indexována a nahodilí hledači by se nemuseli k tématu dostat.. ;o)

z kategorie Web design, přidej na Linkuj.cz, publikováno 17.05.2006 17:11

Komentáře k článku (2×)

01| Andrew (18.05.2006 09:29) | reakce

GRavatar

Předně si dovolím upozornit, že v násobení zcela jistě chyba není. Jsouce oba činitelé celočíselní, bude i výsledek celočíselný. IMHO předvídatelně ;) Co mě překvapuje víc, je, že PgSQL u dělení automaticky nezmění typ výsledku. Třeba v opovrhovaném MySQL to funguje podle očekávání.

Nahodil jsem PgSQL (8.1) a jal se bádat. A zjistil jsem, že aby to fungovalo, jak má, je potřeba, aby alespoň jedno číslo ve vzorci bylo desetinné. Tzn. řešení je např toto: round(SUM(price*(tax+100.0)/100)) INTO not_paid, což je IMHO mnohem přehlednější a elegantnější než to přetypování.

02| xom (18.05.2006 09:36) | reakce

GRavatar

|1| - reakce na Andrew: Nojo, opět mé unáhlené konce.. Prvně jsem zkoušel přetypovat celý vzorec, ale to nepomáhalo, tudíž jsem to prdnul na první pozici, kde to bylo žádoucí.. ;o)

Verze s desetinnou stovkou vypadá dobře a hlavně nemůže dojít k přetečení čísla definovaného přetypováním, díky za analýzu.. Akorát nechápu, proč PgSQL natvrdo přetypovává na Integer, když na každou jinou prkotinu v chybných datových typech upozorňuje a kód neprovede..

Váš komentář:
Jméno
Email (nezobrazí se, identifikace Gravataru)
URI
Okno pro text: zmenšit/zvětšit.

Převažující barva nebe:

Nápověda sytaxe komentářů

Reakci na předchozí komentář můžete učinit napsáním např. [2] či stisknutím odkazu reakce u dotyčného komentáře.

Základní formátování textu - zvýrazněné písmo je v Texy! definováno následovně *pro kurzívu* a **pro tučný řez**.

Odkazy se převádějí automaticky, ale dá se upravit slovní spojení, které bude na dotyčnou adresu ukazovat - např. "xomův fotoblog":[http://www.xom-tom.com/].

Další možnosti syntaxe

Komentáře formátuje Texy! Podrobná dokumentace syntaxe je ka nalezení na oficiálních stránkách.

» Skrýt nápovědu

© 2004-2008 Tom Hnatovsky - Všechna práva vyhrazena
TOPlist