Обсуждение: How to use result column names in having cause

Поиск
Список
Период
Сортировка

How to use result column names in having cause

От
"Andrus"
Дата:
CREATE TEMP TABLE foo( bar integer );

SELECT 123 AS x
  FROM foo
  GROUP BY 1
  HAVING x> AVG(bar)

causes

ERROR:  column "x" does not exist

Why ? How to make this working ?

In real application I have long expression instead of 123 and do'nt want
 repeat this expression in HAVING clause.

In VFP this select works OK.

Andrus.



Re: How to use result column names in having cause

От
"chris smith"
Дата:
On 3/31/06, Andrus <eetasoft@online.ee> wrote:
> CREATE TEMP TABLE foo( bar integer );
>
> SELECT 123 AS x
>   FROM foo
>   GROUP BY 1
>   HAVING x> AVG(bar)
>
> causes
>
> ERROR:  column "x" does not exist
>
> Why ? How to make this working ?
>
> In real application I have long expression instead of 123 and do'nt want
>  repeat this expression in HAVING clause.

You have to repeat the expression. "AS" changes the output name, it
can't be used either in the where clause or any other limiting factor
like 'having':

test=# create table t1(a int);
test=# insert into t1(a) values (1);
test=# SELECT a AS x from t1 where x=1;
ERROR:  column "x" does not exist

--
Postgresql & php tutorials
http://www.designmagick.com/

Re: How to use result column names in having cause

От
"Andrus"
Дата:
>> In real application I have long expression instead of 123 and do'nt want
>>  repeat this expression in HAVING clause.
>
> You have to repeat the expression. "AS" changes the output name, it
> can't be used either in the where clause or any other limiting factor
> like 'having':

Doc about HAVING condition says:

Each column referenced in condition must unambiguously reference a grouping
colum

HAVING x> AVG(bar) unambiguously references to a grouping column x

Is this bug ? It is very tedious to repeat same column expression in a
multiple times: one time in column expression, and n times in having clause.

Are there plans to fix this?

Andrus.



Re: How to use result column names in having cause

От
"Andrus"
Дата:
Here is my problematic query which runs OK in other DBMS.

Only way to run this in Postgres is to duplicate reatasum expression two
times in HAVING clause, right ?

Andrus.



SELECT
  'z' as doktyyp,
  r1.dokumnr,
  r1.kuluobjekt as objekt,
  r1.rid2obj,
  r1.rid3obj,
  r1.rid4obj,
  r1.rid5obj,
  r1.rid6obj,
  r1.rid7obj,
  r1.rid8obj,
  r1.rid9obj,
  dok.tasumata,
  dok.raha,

CASE WHEN ( sum(r2.reasumma)-AVG(dok.doksumma-dok.tasumata)>=
   avg(r1.reasumma) AND avg(r1.reasumma)>=0) OR
   ( sum(r2.reasumma)-AVG(dok.doksumma-dok.tasumata)<
   avg(r1.reasumma) AND avg(r1.reasumma)<0)
THEN
  avg(r1.reasumma)
ELSE
  sum(r2.reasumma)-AVG(dok.doksumma-dok.tasumata)
END as reatasum

FROM dok JOIN reakoond r1 USING (dokumnr)
JOIN reakoond r2 USING (dokumnr)

where
( r1.kuluobjekt::VARCHAR(10)||r1.rid2obj::VARCHAR(10)||
r1.rid3obj::VARCHAR(10)||r1.rid4obj::VARCHAR(10)||
r1.rid5obj::VARCHAR(10)||
r1.rid6obj::VARCHAR(10)||r1.rid7obj::VARCHAR(10)||
r1.rid8obj::VARCHAR(10)||r1.rid9obj::VARCHAR(10))>=
( r2.kuluobjekt::VARCHAR(10)||r2.rid2obj::VARCHAR(10)||
r2.rid3obj::VARCHAR(10)||r2.rid4obj::VARCHAR(10)||
r2.rid5obj::VARCHAR(10)||
r2.rid6obj::VARCHAR(10)||r2.rid7obj::VARCHAR(10)||
r2.rid8obj::VARCHAR(10)||r2.rid9obj::VARCHAR(10) )
group by 1,2,3,4,5,6,7,8,9,10,11,12,13
having (reatasum>0 AND avg(r1.reasumma)>=0) OR
      (reatasum<0 AND avg(r1.reasumma)<0)




Re: How to use result column names in having cause

От
"chris smith"
Дата:
On 3/31/06, Andrus <eetasoft@online.ee> wrote:
> >> In real application I have long expression instead of 123 and do'nt want
> >>  repeat this expression in HAVING clause.
> >
> > You have to repeat the expression. "AS" changes the output name, it
> > can't be used either in the where clause or any other limiting factor
> > like 'having':
>
> Doc about HAVING condition says:
>
> Each column referenced in condition must unambiguously reference a grouping
> colum
>
> HAVING x> AVG(bar) unambiguously references to a grouping column x
>
> Is this bug ? It is very tedious to repeat same column expression in a
> multiple times: one time in column expression, and n times in having clause.


But you're not referencing x, you're trying to use AVG(bar) in your expression.


I assume it's this way because the standard says so.. one of the more
knowledgable list members will be able to confirm/deny this.

--
Postgresql & php tutorials
http://www.designmagick.com/

Re: How to use result column names in having cause

От
Robert Treat
Дата:
On Friday 31 March 2006 08:30, chris smith wrote:
> On 3/31/06, Andrus <eetasoft@online.ee> wrote:
> > >> In real application I have long expression instead of 123 and do'nt
> > >> want repeat this expression in HAVING clause.
> > >
> > > You have to repeat the expression. "AS" changes the output name, it
> > > can't be used either in the where clause or any other limiting factor
> > > like 'having':
> >
> > Doc about HAVING condition says:
> >
> > Each column referenced in condition must unambiguously reference a
> > grouping colum
> >
> > HAVING x> AVG(bar) unambiguously references to a grouping column x
> >
> > Is this bug ? It is very tedious to repeat same column expression in a
> > multiple times: one time in column expression, and n times in having
> > clause.
>
> But you're not referencing x, you're trying to use AVG(bar) in your
> expression.
>
>
> I assume it's this way because the standard says so.. one of the more
> knowledgable list members will be able to confirm/deny this.
>

Yes, this behavior is driven by the sql standards. There is actually a very
nice paper on this subject if you are interested
http://web.onetel.com/~hughdarwen/TheThirdManifesto/Importance-of-Column-Names.pdf

--
Robert Treat
Build A Brighter Lamp :: Linux Apache {middleware} PostgreSQL

Re: How to use result column names in having cause

От
Stephan Szabo
Дата:
On Fri, 31 Mar 2006, Andrus wrote:

> >> In real application I have long expression instead of 123 and do'nt want
> >>  repeat this expression in HAVING clause.
> >
> > You have to repeat the expression. "AS" changes the output name, it
> > can't be used either in the where clause or any other limiting factor
> > like 'having':
>
> Doc about HAVING condition says:
>
> Each column referenced in condition must unambiguously reference a grouping
> colum
>
> HAVING x> AVG(bar) unambiguously references to a grouping column x

IIRC technically the query is invalid, because group by isn't supposed to
run on the output of select entries (as I think is stated by "Each
<grouping column reference> shall unambiguously reference a column of the
table resulting from the <from clause>.") and I'd guess this is a side
effect of allowing group by to work on the table resulting from the select
list as well.

I think the SQL way of writing this is to use a subselect and do two
levels (ie, generate a subselect that gives the table you want to group
and use it in the from clause of the outer query that does the grouping).

Re: How to use result column names in having cause

От
Tom Lane
Дата:
"chris smith" <dmagick@gmail.com> writes:
> I assume it's this way because the standard says so..

Right.  From a logical point of view, the HAVING clause has to be
evaluated before the output expressions are computed, so it doesn't
make any sense to expect the output expressions to be available in
HAVING.  An example of why this must be so is
    SELECT x, 1/avg(y) FROM TAB GROUP BY x HAVING avg(y) > 0
If the HAVING clause isn't executed first this may fail with zero-divide
errors.

The real bug here IMHO is that we don't enforce the same rule for
GROUP BY.  Allowing "GROUP BY 1" to reference an output column is
a violation of the spec, which I think we adopted basically because
some other DBMSes do it too, but it's just as semantically nonsensical
as doing it in HAVING would be.  It's a wart on the language that we
can't really get rid of because of backwards-compatibility
considerations, but we're highly unlikely to add more such warts.

BTW, if you're really intent on not writing your big expression twice,
use a sub-select:
    SELECT x
    FROM (SELECT big_expr AS x FROM ...) AS ss
    GROUP BY ...
    HAVING x > ...

            regards, tom lane