Thread: Getting one row for each subquery row...?

Getting one row for each subquery row...?

From
Együd Csaba
Date:
adding comments to a tableHi All,
here are my three tables. I wold like to list them in the following way: I
need all the columns from t_stockchanges, and one field for the pgoductgroup
the t_stockchanges.productid belongs to.

But one product can belong to many group, so i would need one row for each
group for each product.

My bad query is:
------------------------
DB=# select t_stockchanges.productid, (select name from t_productgroups
where id=(select productgroupid from t_prod_in_pgr where
productid=t_stockchanges.productid)) as pgroup from t_stockchanges;
ERROR:  More than one tuple returned by a subselect used as an expression.
DB=#
---------------
Yes, this is absolutelly true, but I would like postgres to give me all the
tuples found. How can I ask him to do so?

Thank you,
-- Csaba

----------------------------------------------------------------------------
----------------------------------------------------
                             Table "public.t_stockchanges"
    Column     |       Type       |                      Modifiers
---------------+------------------+-----------------------------------------
------------
 id            | integer          | not null
 stockid       | integer          | not null
 productid     | integer          | not null
 changeid      | integer          | not null
 quantity      | double precision | not null
 date          | character(19)    | not null
 purchaseprice | double precision | not null
 correction    | double precision | not null
 userid        | integer          | not null
 time          | character(19)    | default to_char(now(), 'YYYY.mm.dd
hh:mi:ss'::text)
 prooftype     | character(10)    | not null default ''
 proofid       | integer          | default 0
Indexes: t_stockchanges_pkey primary key btree (id),
         t_stockchanges_date btree (date),
         t_stockchanges_productid btree (productid)
----------------------------------------------------------------------------
----------------------------------------------------

         Table "public.t_productgroups"
   Column    |         Type          | Modifiers
-------------+-----------------------+-----------
 id          | integer               | not null
 name        | character varying(30) | not null
 description | character varying     |
 root        | boolean               |
Indexes: t_productgroups_pkey primary key btree (id)
----------------------------------------------------------------------------
----------------------------------------------------

     Table "public.t_prod_in_pgr"
     Column     |  Type   | Modifiers
----------------+---------+-----------
 productgroupid | integer | not null
 productid      | integer | not null
----------------------------------------------------------------------------
----------------------------------------------------


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.489 / Virus Database: 288 - Release Date: 2003. 06. 10.


Re: Getting one row for each subquery row...?

From
Dennis Gearon
Date:
First off, I've nerver heard of using Floating point for money. There
**IS** rounding and truncation that goes on, in even double precision.
The bean counters get upset if you lose .0000001 dollars, especially if
it occurs for several million transactions. The usual choice is DECIMAL.

And I'd use some sort of DATE or TIMESTAMP for the date. and time values.

since you didn't supply any notes, it would be easier to understand if
you used foreign key constraints, and a sounder design perhaps.

And so that I can understand my own queries, I indent them etc(postgres
cares not):

select
    t_stockchanges.productid,
    (select
        name from t_productgroups
    where id=
        (select
           productgroupid from t_prod_in_pgr
        where productid=t_stockchanges.productid
        )
    )
as pgroup
from t_stockchanges;

From you table definitions and titles, I assume, 't_prod_in_pgr' is 'product in process'. You are making an assumption
thata user (?) web user (?) can only have on line entered in that table at a time? 

You will have to explain more about this for me to get it, perhaps for others you will not.

Also, it seems to me that 'productgroupid' should be related to 't_productgroups', but I can not tell.

Tell us more, it gets 'curiouser and curiouser'!




Re: Getting one row for each subquery row...?

From
"Nigel J. Andrews"
Date:
On Thu, 19 Jun 2003, Dennis Gearon wrote:

> First off, I've nerver heard of using Floating point for money. There
> **IS** rounding and truncation that goes on, in even double precision.
> The bean counters get upset if you lose .0000001 dollars, especially if
> it occurs for several million transactions. The usual choice is DECIMAL.
>
> And I'd use some sort of DATE or TIMESTAMP for the date. and time values.
>
> since you didn't supply any notes, it would be easier to understand if
> you used foreign key constraints, and a sounder design perhaps.
>
> And so that I can understand my own queries, I indent them etc(postgres
> cares not):
>
> select
>     t_stockchanges.productid,
>     (select
>         name from t_productgroups
>     where id=
>         (select
>            productgroupid from t_prod_in_pgr
>         where productid=t_stockchanges.productid
>         )
>     )
> as pgroup
> from t_stockchanges;
>
> From you table definitions and titles, I assume, 't_prod_in_pgr' is 'product in process'. You are making an
assumptionthat a user (?) web user (?) can only have on line entered in that table at a time? 
>
> You will have to explain more about this for me to get it, perhaps for others you will not.
>
> Also, it seems to me that 'productgroupid' should be related to 't_productgroups', but I can not tell.
>
> Tell us more, it gets 'curiouser and curiouser'!
>

Having said that I'm sure you've worked out the intention is probably:

select t_stockchanges.productid, t_productgroups.name
  from t_stockchanges, t_productgroup, t_prod_in_pgr
  where t_stockchanges.productid = t_prod_in_pgr.productid
     and t_productgroups.id = t_prod_in_pgr.productgroupid
;

Without the foreign keys and other constraints though that could get very
wrong as you pointed out Dennis.


--
Nigel J. Andrews


Re: Getting one row for each subquery row...?

From
"Nigel J. Andrews"
Date:

[Damn, didn't notice the lack of list address in the headers until I'd already
sent this reply. The OP's address is elsewhere in the thread, obviously.]


On Fri, 20 Jun 2003, Együd Csaba wrote:

> Thank you Nigel,
>
> > >
> > > select
> > >     t_stockchanges.productid,
> > >     (select
> > >         name from t_productgroups
> > >     where id=
> > >         (select
> > >            productgroupid from t_prod_in_pgr
> > >         where productid=t_stockchanges.productid
> > >         )
> > >     )
> > > as pgroup
> > > from t_stockchanges;
>
> it also gives the same result as the solution I recevived from the pgsql-sql
> list:
>
> (By Tomasz Myrta) ---------------------------------------
> select
>   t_stockchanges.productid,
>   t_productgroups.name as pgroup
> from
>   t_stockchanges
>   join t_prod_in using (productid)
>   join t_productgroups on (id=productgroupid)
> ------------------------------------------------------------
>
> The only modification I made is the use of distinct clause to avoid the
> repeated rows.

The point about the referential integrity and other constraints, like
uniqueness is that: only with my assumption and not knowledge of what your db
is doing I personnally would not have expected that query to give any duplicate
rows. I would only expect to see duplicate rows if there are duplicate rows in
one or more of your tables. Using foreign keys (which require uniqueness in the
referenced table) would help you avoid such inconsistencies.

For example in your t_prod_in_pgrp table how are you preventing:

productid  |  productgroupid
----------------------------
   234     |     24
   234     |     24
   234     |     24

which in the query I gave would give you three rows the same?

Equally, how are you preventing in t_productgroups:

id   | col1 ...
------------...

 24  |  ...
 24  |  ...

which when combined with the first 'anomoly' would give you six rows the same
from that query?

BTW, the above query while the same as my version (I haven't inspected it so I
take your word for it) is not so good. That is forcing postgresql to join in
the tables in the specified order. Using the join constraints in the where
clause as mine does lets the planner choose what it thinks is the best join
order.


--
Nigel J. Andrews