From: | Sébastien Dinot <sebastien(dot)dinot(at)free(dot)fr> |
---|---|
To: | pgsql-fr-generale(at)postgresql(dot)org |
Subject: | Re: Calcul de médiane |
Date: | 2008-06-03 23:10:42 |
Message-ID: | 20080603231042.GB7922@dinot.net |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-fr-generale |
Bonjour,
En février 2007, j'avais demandé ici même s'il existait une méthode
prête à l'emploi pour calculer la médiane d'un ensemble de valeurs :
http://archives.postgresql.org/pgsql-fr-generale/2007-02/msg00009.php
J'avais fini par écrire une procédure stockée et à en expliquer les
grandes lignes sur la liste :
http://archives.postgresql.org/pgsql-fr-generale/2007-02/msg00018.php
Sur le coup, j'ai sérieusement manqué de jugeotte en négligeant de
joindre le code à l'explication. Or, comme mon message initial est le
premier lien renvoyé par Google lorsqu'on recherche les mots clés
« PostgreSQL médiane », plusieurs personnes m'ont depuis demandé si je
pouvais leur fournir le code de ma procédure. Il semble donc pertinent
de poster ledit code ici, même avec 16 mois de retard. Avant que l'un
d'entre vous ne s'exclame « Et la licence !? », je précise tout de
suite que toute personne intéressée par ce modeste code peut
l'utiliser et l'adapter comme bon lui semble.
Si d'autres ont des critiques ou des améliorations en tête, qu'ils
n'hésitent pas un instant à en faire profiter tout le monde.
A++, Sébastien
----------------------------------------------------------------------
CREATE FUNCTION mediane_cotisation (VARCHAR, DATE) RETURNS NUMERIC(10,2) AS
'
DECLARE
val_type ALIAS FOR $1; -- Type d'adhesion
val_date ALIAS FOR $2; -- Date a laquelle se rapporte la mediane
nb_adh INT;
montant_inf NUMERIC(10,2);
montant_sup NUMERIC(10,2);
val_med NUMERIC(10,2);
curseur CURSOR (moitie INT) FOR
SELECT SUM(c.montant)
FROM cotisation AS c
JOIN adhesion AS a ON c.id_adhesion = a.id_adhesion
WHERE c.date_effet <= val_date
AND c.date_echeance >= val_date
AND a.type_adhesion = val_type
GROUP BY c.id_adhesion
ORDER BY SUM(c.montant)
OFFSET moitie
LIMIT 2;
BEGIN
nb_adh := ( SELECT COUNT(DISTINCT c.id_adhesion)
FROM cotisation AS c
JOIN adhesion AS a ON c.id_adhesion = a.id_adhesion
WHERE c.date_effet <= val_date
AND c.date_echeance >= val_date
AND a.type_adhesion = val_type );
IF nb_adh % 2 = 0 THEN
OPEN curseur((nb_adh / 2) - 1);
FETCH curseur INTO montant_inf;
FETCH curseur INTO montant_sup;
CLOSE curseur;
val_med := (montant_inf + montant_sup) / 2.0;
ELSE
OPEN curseur(nb_adh / 2);
FETCH curseur INTO montant_inf;
CLOSE curseur;
val_med := montant_inf;
END IF;
RETURN val_med;
END;
' LANGUAGE 'plpgsql';
----------------------------------------------------------------------
--
Sébastien Dinot, sebastien(dot)dinot(at)free(dot)fr
http://sebastien.dinot.free.fr/
Ne goûtez pas au logiciel libre, vous ne pourriez plus vous en passer !
From | Date | Subject | |
---|---|---|---|
Next Message | Valérie SCHNEIDER | 2008-06-04 07:37:36 | Re: Problème de select suivant un update |
Previous Message | Guillaume Lelarge | 2008-06-03 21:49:00 | Re: Problème de select suivant un update |