Analýza domén

Z PostgreSQL
Přejít na: navigace, hledá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.