Statistiques système
Avant de lancer le vôtre, jetez un œil à la table système pg_statistic
ou la vue pg_stats
:
Il peut déjà avoir certaines des statistiques que vous êtes sur le point de calculer. Il est rempli par ANALYZE
, vous pouvez donc l'exécuter pour les nouvelles tables (ou toutes) avant de vérifier.
-- ANALYZE tbl; -- optionally, to init / refresh
SELECT * FROM pg_stats
WHERE tablename = 'tbl'
AND schemaname = 'public';
Fonction plpgsql dynamique générique
Vous souhaitez renvoyer la valeur minimale pour chaque colonne d'une table donnée . Ce n'est pas une tâche triviale, car une fonction (comme SQL en général) demande de connaître le type de retour au moment de la création - ou du moins au moment de l'appel à l'aide de types de données polymorphes.
Cette fonction fait tout automatiquement et en toute sécurité. Fonctionne pour tous table, tant que la fonction d'agrégation min()
est autorisé pour chaque colonne. Mais vous avez besoin pour vous familiariser avec PL/pgSQL.
CREATE OR REPLACE FUNCTION f_min_of(_tbl anyelement)
RETURNS SETOF anyelement
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE (
SELECT format('SELECT (t::%2$s).* FROM (SELECT min(%1$s) FROM %2$s) t'
, string_agg(quote_ident(attname), '), min(' ORDER BY attnum)
, pg_typeof(_tbl)::text)
FROM pg_attribute
WHERE attrelid = pg_typeof(_tbl)::text::regclass
AND NOT attisdropped -- no dropped (dead) columns
AND attnum > 0 -- no system columns
);
END
$func$;
Appel (important !) :
SELECT * FROM f_min_of(NULL::tbl); -- tbl being the table name
db<>violon ici
Ancien sqlfiddle
Vous devez comprendre ces concepts :
- SQL dynamique dans plpgsql avec
EXECUTE
- Types polymorphes
- Types de lignes et types de tables dans Postgres
- Comment se défendre contre l'injection SQL
- Fonctions d'agrégation
- Catalogues système
Réponse connexe avec une explication détaillée :
- Nom de table en tant que Paramètre de la fonction PostgreSQL
- Refactoriser une fonction PL/pgSQL pour renvoyer la sortie de diverses requêtes SELECT
- Type de données Postgres
- Comment définir la valeur d'un champ de variable composite à l'aide de SQL dynamique
- Comment vérifier si une table existe dans un schéma donné
- Sélectionner des colonnes avec des noms de colonne particuliers dans PostgreSQL
- Générer une série de dates - en utilisant le type de date comme entrée
Difficulté particulière avec l'incompatibilité de type
Je profite de Postgres définissant un type de ligne pour chaque table existante. En utilisant le concept de types polymorphes, je suis capable d'en créer un fonction qui fonctionne pour n'importe quelle table.
Cependant, certaines fonctions d'agrégation renvoient des types de données liés mais différents par rapport à la colonne sous-jacente. Par exemple, min(varchar_column)
renvoie text
, qui est compatible au niveau des bits, mais pas exactement le même type de données. Les fonctions PL/pgSQL ont un point faible ici et insistent sur les types de données exactement comme déclaré dans le RETURNS
clause. Aucune tentative de cast, pas même de casts implicites, sans parler des casts d'assignation.
Cela devrait être amélioré. Testé avec Postgres 9.3. Je n'ai pas retesté avec 9.4, mais je suis presque sûr que rien n'a changé dans ce domaine.
C'est là que cette construction entre en jeu comme solution de contournement :
SELECT (t::tbl).* FROM (SELECT ... FROM tbl) t;
En convertissant explicitement la ligne entière en type de ligne de la table sous-jacente, nous forçons les transtypages d'affectation à obtenir les types de données d'origine pour chaque colonne.
Cela peut échouer pour certaines fonctions d'agrégation. sum()
renvoie numeric
pour une sum(bigint_column)
pour tenir compte d'une somme dépassant le type de données de base. Relancer vers bigint
peut échouer ...