DevHeads.net

How to refer to computed columns from other computed columns?

I'm converting some procedural code to SQL as an experiment. Here's the
pseudocode:

c = a - b
if c < 0 then d = 'no'
else d = 'yes'

In SQL, I've got this:

select a, b, a - b as c,
case when a - b < 0 then 'no'
else 'yes'
end as d

from foo;

This is a trivial example, but you can see how I calculate a - b two
separate times.

In reality, I have much nastier calculations and they happen more than
just twice.

I'm looking for an elegant solution for this puzzle. I don't want to
repeat that a - b part over and over because I likely will need to
change how c gets defined and I don't want to have to change more than
one place in the code.

All I can come up with so far is to use a view and then another view on
top of that one:

create view v1 as
select a, b, a - b as c
from foo;

create view v2 as
select a, b, c,
case when c < 0 then 'no'
else 'yes'
end as d
from v1;

This is better than the first solution because c is only defined in a
single place. Is this the best possible solution?

Thanks for the help.

Matt

Comments

Re: How to refer to computed columns from other comput

By Eric Ndengang at 08/16/2010 - 10:46

Am 16.08.2010 14:45, schrieb Matthew Wilson:
with table_1 as (select a,b, a-b as c from foo)
Select a,b, c,
case when c<0 then 'no'
else 'yes' end as d
from table_1;
I hope , it will help you

Re: How to refer to computed columns from other comput

By Tom Lane at 08/16/2010 - 10:26

Matthew Wilson < ... at tplus1 dot com> writes:
Note that you don't actually need a view, as you can just write the
subselect in-line:

select a, b, c,
case when c < 0 then 'no'
else 'yes'
end as d
from (select a, b, a - b as c from foo) as v1;

This is the standard method for avoiding repeat calculations in SQL.

One thing to keep in mind is that the planner will usually try to
"flatten" a nested sub-select (and whether it was written out manually
or pulled from a view does not matter here). This will result in the
sub-select's expressions getting inlined into the parent, so that the
calculations will actually get done more than once. If you're trying
to reduce execution time not just manual labor, you may want to put an
"offset 0" into the sub-select to create an optimization fence. But
test whether that really saves anything --- if there are bigger joins
or additional WHERE conditions involved, you can easily lose more than
you gain by preventing flattening.

regards, tom lane

Re: How to refer to computed columns from other comput

By Matthew Wilson at 08/16/2010 - 13:49

On Mon Aug 16 10:26:36 2010, Tom Lane wrote:
Thanks so much for the help!

I don't care if the code is rearranged so that c is replaced with an
inline definition during compilation. I'm not concerned about
efficiency here. I just don't want to have to redefine it manually over
and over again, because I know that as I update how c is defined, I'll
forget to update it everywhere.

Maybe sql needs a preprocessing macro language like C.

<ducks>

Matt

Re: How to refer to computed columns from other comput

By Boszormenyi Zoltan at 08/16/2010 - 14:45

Matthew Wilson írta:
Or maybe we can dust off my GENERATED column patch
I posted here in 2006. :-)

Best regards,
Zoltán Böszörményi

Re: How to refer to computed columns from other comput

By Alvaro Herrera at 08/16/2010 - 16:18

Excerpts from Boszormenyi Zoltan's message of lun ago 16 14:45:07 -0400 2010:
Hmm, that seems entirely unrelated ...

Re: How to refer to computed columns from other comput

By Boszormenyi Zoltan at 08/17/2010 - 08:29

Alvaro Herrera írta:
What makes you think so? A generated column would put
the work into INSERT and UPDATE statements, SELECTs
would be faster and this way re-typing the same expression
would be avoided. The generated column's definition is defined
at one central place, with the type modifier on such a column in
CREATE or ALTER TABLE , so the problem of the OP
would be also solved.

There was only one drawback, as Tom Lane pointed out a while back,
but this was explicitely covered by the SQL standard at the time,
it said that before triggers cannot look at the content of the generated
columns.

And with HOT and no indexes on the generated column, most
of the bloat would also be avoided that comes from the extra
internal UPDATE that such a column would introduce.

Re: How to refer to computed columns from other comput

By Thom Brown at 08/16/2010 - 14:51

2010/8/16 Boszormenyi Zoltan < ... at cybertec dot at>:
You mean this?:
<a href="http://archives.postgresql.org/pgsql-hackers/2006-07/msg00543.php" title="http://archives.postgresql.org/pgsql-hackers/2006-07/msg00543.php">http://archives.postgresql.org/pgsql-hackers/2006-07/msg00543.php</a>
And this?: <a href="http://archives.postgresql.org/pgsql-hackers/2006-08/msg00038.php" title="http://archives.postgresql.org/pgsql-hackers/2006-08/msg00038.php">http://archives.postgresql.org/pgsql-hackers/2006-08/msg00038.php</a>
And this?: <a href="http://archives.postgresql.org/pgsql-patches/2007-04/msg00107.php" title="http://archives.postgresql.org/pgsql-patches/2007-04/msg00107.php">http://archives.postgresql.org/pgsql-patches/2007-04/msg00107.php</a>