2010-02-18 4 views
1

J'ai écrit une fonction récursive et en fonction de la sortie, j'ai besoin de sélectionner différents champs. Ma question est maintenant, comment puis-je faire cela plusieurs fois sans avoir à appeler la fonction plus d'une fois? Ce que je fais en ce moment, c'est simplement d'utiliser la condition CASE WHEN... et de vérifier à chaque fois ce que les fonctions retournent. (Ceci est seulement un code pseudo et ne fait rien de réel, il est juste pour la compréhension)PostgreSQL Sélections conditionnelles

SELECT 
id, 
(CASE WHEN (function(id) > 0) 
    THEN field1 
    ELSE field2 
END) as value1, 
(CASE WHEN (function(id) > 0) 
    THEN field3 
    ELSE field4 
END) as value2, 
(CASE WHEN (function(id) > 0) 
    THEN field5 
    ELSE field6 
END) as value3 
FROM table1 
... 

Comment puis-je optimiser cette requête et appeler la fonction qu'une seule fois? Merci d'avance!

+0

Quelle est la langue de la fonction? –

+0

La langue est PL/pgSQL. – stefita

+0

Il est étrange que vous ayez accepté la réponse pour utiliser IMMUTABLE mais vous dites dans un commentaire que votre fonction "sélectionne une valeur d'une autre table et qu'elle pourrait être changée pour cet identifiant particulier". J'espère que vous n'avez pas marqué cette fonction IMMUTABLE puisque Postgres ne dit pas combien de temps il met en cache le résultat d'une fonction immuable. –

Répondre

2

Si la fonction est déclarée IMMUTABLE, il est sûr de l'appeler plusieurs fois, car il ne sera pas réévaluées.

De l'docs:

IMMUTABLE indique que la fonction ne peut pas modifier la base de données et renvoie toujours le même résultat quand on donne les mêmes valeurs d'argument; c'est-à-dire qu'il ne fait pas de recherche dans la base de données ou n'utilise pas d'informations qui ne sont pas directement présentes dans sa liste d'arguments. Si cette option est donnée, tout appel de la fonction avec des arguments tout-constants peut être immédiatement remplacé par la valeur de la fonction.

+0

Que se passe-t-il si le résultat change pour les mêmes arguments? – stefita

+0

@stefita: vous ne devriez pas marquer de telles fonctions comme 'IMMUTABLE'. http://www.postgresql.org/docs/current/static/xfunc-volatility.html – Quassnoi

+0

@stefita: Vous voulez dire comme clock_timestamp()? Alors vous le déclarez VOLATILE et Postgres l'invoquera chaque fois qu'il le verra. Que pourrait-il faire d'autre? Mais votre exemple ressemble à la fonction (id) renvoie la même chose mais vous en avez besoin pour sélectionner 3 champs différents –

2

utiliser une sous-requête:

SELECT foo, bar, result 
FROM (
SELECT ..., function(id) AS result 
.... 
) as tmp 
1

Vous pourriez être en mesure d'utiliser quelque chose de tuple funky comme:

SELECT id, 
CASE WHEN function(id) > 0 
    THEN (field1, field3, field5) 
    ELSE (field2, field4, field6) 
END as (value1, value2, value3) 

mais je n'ai aucune expérience avec cette syntaxe