Transformace částky (čísla) na slovní vyjádření

Z PostgreSQL
Přejít na: navigace, hledání

K získání slovního vyjádření číselné hodnoty lze použít následující funkci. Číslo je zobrazeno bez mezer (ve tvaru určeném pro složenky). Rozsah funkce je 1..999 999 999. Inspirováno Ondřejem Vanišem, autor Pavel Stěhule.

CREATE OR REPLACE FUNCTION to_char_nw(int)
RETURNS varchar AS $$
DECLARE dict varchar[][] = ARRAY[
                                 ARRAY['jedna','dva','tři','čtyři','pět','šest','sedm','osm','devět'],
                                 ARRAY['','dvacet','třicet','čtyřicet','padesát','šedesát','sedmdesát','osmdesát','devadesát'],
                                 ARRAY['sto','dvěstě','třista','čtyřista','pětset','šestset','sedmset','osmset','devětset'],
                                 ARRAY['tisíc','tisíce','tisíce','tisíce','tisíc','tisíc','tisíc','tisíc','tisíc'],
                                 ARRAY['milion','miliony','miliony','miliony','milionů','milionů','milionů','milionů','milionů']
                                ];
        dict20 varchar[] = ARRAY['deset','jedenáct','dvanáct','třínáct','čtrnáct',
                                 'patnáct','šestnáct','sedmnáct','osmnáct','devatenáct'];
  accu varchar = '';
  auxi int = $1;
  stack int;
BEGIN
  WHILE auxi > 0 OR stack IS NOT NULL LOOP
    stack := COALESCE(stack, CASE WHEN auxi >= 1000
                                  THEN auxi
                                  ELSE NULL END);
    auxi := CASE WHEN auxi >= 1000000
                 THEN auxi/1000000
                 WHEN auxi >= 1000
                 THEN auxi/1000
                 ELSE auxi END;
    accu := accu || CASE WHEN auxi >= 100
                         THEN dict[3][auxi/100]
                         WHEN auxi >= 20
                         THEN dict[2][auxi/10]
                         WHEN auxi >= 10
                         THEN dict20[auxi - 9]
                         ELSE CASE WHEN stack IS NULL
                                   THEN dict[1][auxi]
                                   WHEN stack >= 1000000
                                   THEN CASE WHEN (stack/1000000) = 1
                                        THEN 'jeden'
                                        ELSE dict[1][auxi] END
                                   WHEN stack >= 1000
                                   THEN CASE WHEN (stack/1000 % 10) = 1
                                        THEN 'jeden'
                                        ELSE dict[1][auxi] END
                              END
                    END;
    auxi := CASE WHEN auxi >= 100
                 THEN auxi % 100
                 WHEN auxi >= 20
                 THEN auxi % 10
                 ELSE 0 END;
    IF stack IS NOT NULL AND auxi = 0 THEN
      SELECT INTO
             accu, auxi, stack
             accu || CASE WHEN stack >= 10000000
                          THEN 'miliónů'
                          WHEN stack >= 1000000
                          THEN dict[5][stack/1000000]
                          WHEN stack >= 10000
                          THEN 'tisíc'
                          WHEN stack >= 1000
                          THEN dict[4][stack/1000] END,
             CASE WHEN stack >= 1000000
                  THEN stack % 1000000
                  WHEN stack >= 1000
                  THEN stack % 1000 END,
             NULL;
    END IF;
  END LOOP;
  RETURN CASE WHEN accu <> ''
              THEN accu
              ELSE 'nula' END;
  RETURN accu;
END;
$$ LANGUAGE plpgsql;

Použití:

postgres=# SELECT to_char_nw(21021);
         to_char_nw
-----------------------------
 dvacetjedentisícdvacetjedna
(1 row)