Analýza domén
Převzato z http://www.depesz.com/index.php/2008/12/01/getting-list-of-most-common-domains/#comment-27066
Následující kód je v podstatě první ukázkou jedné z vlastností PostgreSQL a to možnosti volání SRF funkcí v normálním kontextu. Tuto vlastnost nemám rád, ale v tomto případě má smysl. Představte si, že máte seznam (log) domén - a nyní budete chtít dohledat četnost jednotlivých domén. Tedy uložené domény musíme transformovat (např. psql.cz na psql.cz a cz). Tj. musíme namnožit řádky - což v čistém SQL nelze - (v ANSI SQL 200x by bylo možné použít CTE, patrně by se nejednalo o žádný zázrak). Možnosti jsou 2 - buďto napíšeme klasickou SRF funkci nad konkrétní tabulkou (což je metoda, kterou preferuji) nebo funkci, která převede hodnotu domény na hierarchický seznam poddomén.
a) připravím si pomocné funkce:
postgres=# create or replace function domain_list(varchar[])
returns setof varchar as $$
select array_to_string($1,’.')
union all
select domain_list($1[2:array_upper($1,1)])
where array_upper($1,1) > 1
$$ language sql immutable strict;
CREATE FUNCTION
postgres=# select domain_list(array['a','b','c','d']);
domain_list
————-
a.b.c.d
b.c.d
c.d
d
(4 rows)
postgres=# create or replace function domain_list(varchar)
returns setof varchar as $$
select domain_list(string_to_array($1, ‘.’))
$$ language sql immutable strict;
CREATE FUNCTION
postgres=# select domain_list(’a.b.c.d’);
domain_list
————-
a.b.c.d
b.c.d
c.d
d
b) pro tabulku domains si funkcí domain_list namnožíme řádky:
postgres=# select * from domains;
d
----------------
pgsql.cz
lmc.cz
postgresql.org
gnome.org
(4 rows)
postgres=# select domain_list(d), d from domains;
domain_list | d
----------------+----------------
pgsql.cz | pgsql.cz
cz | pgsql.cz
lmc.cz | lmc.cz
cz | lmc.cz
postgresql.org | postgresql.org
org | postgresql.org
gnome.org | gnome.org
org | gnome.org
(8 rows)
Výsledek po agregaci:
postgres=# select domain_list(d), count(*)
from domains
group by domain_list(d)
order by 2 desc, 1;
domain_list | count
----------------+-------
cz | 2
org | 2
gnome.org | 1
lmc.cz | 1
pgsql.cz | 1
postgresql.org | 1
(6 rows)
Docela hezký trik.