Thread: Evaluate only one CASE WHEN in a select

Evaluate only one CASE WHEN in a select

From
"dcrespo"
Date:
Hi everybody,

I'm implementing something like this:

SELECT
    CASE WHEN add_numbers(t1.main_number,t2.main_number)>100
        THEN t1.description1
        ELSE t2.description1
    END AS number_description1,
    CASE WHEN add_numbers(t1.main_number,t2.main_number)>100
        THEN t1.description2
        ELSE t2.description2
    END AS number_description2
FROM table1 t1, table2 t2;

Is there a way to evaluate the 'CASE WHEN' only once?

Thanks

Daniel


Re: Evaluate only one CASE WHEN in a select

From
Guy Rouillier
Date:
dcrespo wrote:
> Hi everybody,
>
> I'm implementing something like this:
>
> SELECT
>     CASE WHEN add_numbers(t1.main_number,t2.main_number)>100
>         THEN t1.description1
>         ELSE t2.description1
>     END AS number_description1,
>     CASE WHEN add_numbers(t1.main_number,t2.main_number)>100
>         THEN t1.description2
>         ELSE t2.description2
>     END AS number_description2
> FROM table1 t1, table2 t2;
>
> Is there a way to evaluate the 'CASE WHEN' only once?

Sure, see the implementation of CASE here:

http://www.postgresql.org/docs/8.2/static/functions-conditional.html

Not sure what you are looking for, though, since your condition in both
CASEs above is exactly the same.

--
Guy Rouillier

Re: Evaluate only one CASE WHEN in a select

From
"dcrespo"
Date:
On Apr 11, 11:35 pm, guyr-...@burntmail.com (Guy Rouillier) wrote:
> dcrespo wrote:
> > Hi everybody,
>
> > I'm implementing something like this:
>
> > SELECT
> >     CASE WHEN add_numbers(t1.main_number,t2.main_number)>100
> >         THEN t1.description1
> >         ELSE t2.description1
> >     END AS number_description1,
> >     CASE WHEN add_numbers(t1.main_number,t2.main_number)>100
> >         THEN t1.description2
> >         ELSE t2.description2
> >     END AS number_description2
> > FROM table1 t1, table2 t2;
>
> > Is there a way to evaluate the 'CASE WHEN' only once?
>
> Sure, see the implementation of CASE here:
>
> http://www.postgresql.org/docs/8.2/static/functions-conditional.html
>
> Not sure what you are looking for, though, since your condition in both
> CASEs above is exactly the same.
>
> --
> Guy Rouillier
>
> ---------------------------(end of broadcast)---------------------------
> TIP 3: Have you checked our extensive FAQ?
>
>                http://www.postgresql.org/docs/faq- Hide quoted text -
>
> - Show quoted text -

They are exactly the same, that's why I want to evaluate it only once
and, depending on it, put the corresponding value into two different
fields that must be returned, instead of evaluating once for each
field. Any insight?

Thank you

Daniel


Re: Evaluate only one CASE WHEN in a select

From
Tom Lane
Date:
"dcrespo" <dcrespo@gmail.com> writes:
> They are exactly the same, that's why I want to evaluate it only once
> and, depending on it, put the corresponding value into two different
> fields that must be returned, instead of evaluating once for each
> field. Any insight?

There's no solution that wouldn't cost you more than double evaluation,
for such a simple expression.

The general solution is to use two levels of SELECT:

    select ..., x, x, ...
      from (select ..., big-expr as x, ... from ... offset 0) ss;

You need the "offset 0" (which is otherwise a no-op) to prevent the
planner from folding the two selects into a single level and ending up
with two copies of big-expr anyway.  The runtime overhead associated
with the extra plan level is about going to eat up whatever you might
save in this example, though with a seriously expensive expression
(for instance, a function that does some fairly expensive SELECT itself)
you might find it worth doing.

            regards, tom lane

Re: Evaluate only one CASE WHEN in a select

From
"dcrespo"
Date:
On Apr 12, 4:30 pm, t...@sss.pgh.pa.us (Tom Lane) wrote:
> "dcrespo" <dcre...@gmail.com> writes:
> > They are exactly the same, that's why I want to evaluate it only once
> > and, depending on it, put the corresponding value into two different
> > fields that must be returned, instead of evaluating once for each
> > field. Any insight?
>
> There's no solution that wouldn't cost you more than double evaluation,
> for such a simple expression.
>
> The general solution is to use two levels of SELECT:
>
>         select ..., x, x, ...
>           from (select ..., big-expr as x, ... from ... offset 0) ss;
>
> You need the "offset 0" (which is otherwise a no-op) to prevent the
> planner from folding the two selects into a single level and ending up
> with two copies of big-expr anyway.  The runtime overhead associated
> with the extra plan level is about going to eat up whatever you might
> save in this example, though with a seriously expensive expression
> (for instance, a function that does some fairly expensive SELECT itself)
> you might find it worth doing.
>
>                         regards, tom lane
>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Have you searched our list archives?
>
>                http://archives.postgresql.org/
Thank you, Tom.

In your example, "x,x" seems to be the same value. I don't want that
exactly. Here is another example:

SELECT
    CASE WHEN is_odd(t.number) THEN 'Update' ELSE 'Insert' END AS
action,
    CASE WHEN is_odd(t.number) THEN t.number ELSE NULL END AS number,
FROM ... ;

As you can see, is_odd function (only a function example) is being run
twice with exactly the same parameters to put a value into action
field and into number field. Since it's the same function call, I want
it to be run only once and put the above values into their
corresponding fields. My actual function is not that expensive, but
has to be run for every retrieved row, obviously. Does this change
your explanation?

Thank you

Daniel



Re: Evaluate only one CASE WHEN in a select

From
Guy Rouillier
Date:
dcrespo wrote:
>
> SELECT
>     CASE WHEN is_odd(t.number) THEN 'Update' ELSE 'Insert' END AS
> action,
>     CASE WHEN is_odd(t.number) THEN t.number ELSE NULL END AS number,
> FROM ... ;
>
> As you can see, is_odd function (only a function example) is being run
> twice with exactly the same parameters to put a value into action
> field and into number field. Since it's the same function call, I want
> it to be run only once and put the above values into their
> corresponding fields. My actual function is not that expensive, but
> has to be run for every retrieved row, obviously. Does this change
> your explanation?

If your objective is to run a stored procedure once but return several
values, look at either defining multiple OUT parameters, or returning a
record type.

--
Guy Rouillier