Thread: A subselect in an aggregate

A subselect in an aggregate

From
"Bryan White"
Date:
This statement works:
select date, (select sum(qty * price) from orderdetail d where d.orderid =
orders.orderid) from orders

But when I try to do something like this:

select date, sum(select sum(qty * price) from orderdetail d where d.orderid
= orders.orderid) from orders group by date

I get ERROR: parser: parse error at or near "select"

Is there a way to apply an agregate function to a subselect like this?




Re: A subselect in an aggregate

From
Ed Loehr
Date:
Bryan White wrote:
> 
> This statement works:
> select date, (select sum(qty * price) from orderdetail d where d.orderid =
> orders.orderid) from orders
> 
> But when I try to do something like this:
> 
> select date, sum(select sum(qty * price) from orderdetail d where d.orderid
> = orders.orderid) from orders group by date
> 
> I get ERROR: parser: parse error at or near "select"
> 
> Is there a way to apply an agregate function to a subselect like this?

Avoiding the question, I'm wondering if this simpler form wouldn't be
what you're after?
select o.date, sum(d.qty * d.price) from orderdetail d, orders owhere d.orderid = o.orderidgroup by o.date

Regards,
Ed Loehr


Re: A subselect in an aggregate

From
"Bryan White"
Date:

> Bryan White wrote:
> >
> > This statement works:
> > select date, (select sum(qty * price) from orderdetail d where d.orderid
=
> > orders.orderid) from orders
> >
> > But when I try to do something like this:
> >
> > select date, sum(select sum(qty * price) from orderdetail d where
d.orderid
> > = orders.orderid) from orders group by date
> >
> > I get ERROR: parser: parse error at or near "select"
> >
> > Is there a way to apply an agregate function to a subselect like this?
>
> Avoiding the question, I'm wondering if this simpler form wouldn't be
> what you're after?
>
> select o.date, sum(d.qty * d.price)
> from orderdetail d, orders o
> where d.orderid = o.orderid
> group by o.date

This is very slow (acutally I killed it after about 5 minutes):
select o.date,sum(d.qty * d.price) from orderdetail d,orders o where o.date
= '6/1/2000' group by o.date;
Explained:
Aggregate  (cost=0.00..41074641.24 rows=120300337 width=20) ->  Group  (cost=0.00..38067132.80 rows=1203003374
width=20)      ->  Nested Loop  (cost=0.00..35059624.37 rows=1203003374 width=20)             ->  Index Scan using
iorddate3on orders o
 
(cost=0.00..6917.34 rows=1808 width=4)             ->  Seq Scan on orderdetail d  (cost=0.00..12733.78
rows=665378 width=16)

Doing a squential scan of orderdetail inside a loop seems to be what kills
it.

This is quick (it takes a couple of seconds):
select o.date,(select sum(od.qty * od.price) from orderdetail od where
od.orderid = o.orderid) from orders o where o.date = '6/1/2000';
Explained:
Index Scan using iorddate3 on orders o  (cost=0.00..6917.34 rows=1808
width=8) SubPlan   ->  Aggregate  (cost=45.24..45.24 rows=1 width=16)         ->  Index Scan using iodid on orderdetail
od (cost=0.00..45.21
 
rows=11 width=16)

I suppose I can do my own grouping on the result data but I would like to
avoid that if I could.  Which brings me back to the original question:  Is
there a way to apply an aggregate function to a subselect?





Re: A subselect in an aggregate

From
Tom Lane
Date:
"Bryan White" <bryan@arcamax.com> writes:
> This is very slow (acutally I killed it after about 5 minutes):
> select o.date,sum(d.qty * d.price) from orderdetail d,orders o where o.date
> = '6/1/2000' group by o.date;

> This is quick (it takes a couple of seconds):
> select o.date,(select sum(od.qty * od.price) from orderdetail od where
> od.orderid = o.orderid) from orders o where o.date = '6/1/2000';

Well, they're not computing the same thing, are they?  Since there's no
constraint on d.orderid in the first example, you're asking for the sum
over ALL orderdetail records ... repeated over again for each order
record.  For equivalent constraints, I'd expect the first form to be
at least as fast as the second, probably faster.

> Which brings me back to the original question:  Is
> there a way to apply an aggregate function to a subselect?

Sure --- you just forgot that a sub-select expression requires its
very own parentheses, so you need two sets:sum((select ....))
But the other way is probably better...
        regards, tom lane