Thread: Problem using Subselect results

Problem using Subselect results

From
oheinz@stud.fbi.fh-darmstadt.de
Date:
I want to use the result of a subselect as condition of another one.

CREATE VIEW my_view AS SELECT b,c
(SELECT a, b FROM table2 WHERE b=1) my_ab,
(SELECT  c FROM table3, my_ab WHERE table3.a=my_ab.a) my_c;

does return "relation my_ab unknown". it is not just a problem of execution 
order - if i turn it the other way round it's still the same.

Am I just trying to do something really stupid? And what for is the (necessary) 
AS statement for subselects, if it's not possible to access their results by 
that name?
As I need the result of a subselect  in several other subselects it's not 
possible to transform them into a cascade of sub, subsub, subsubsub.... selects.
Any ideas? 

TIA,
Oliver 


-------------------------------------------------
This mail sent through IMP: http://horde.org/imp/


Re: Problem using Subselect results

From
Bruno Wolff III
Date:
On Wed, Jul 23, 2003 at 14:51:48 +0200, oheinz@stud.fbi.fh-darmstadt.de wrote:
> I want to use the result of a subselect as condition of another one.

The two selects you use ar both from items at the same level and hence can't
reference one another. In your example below you could just use a join.

> CREATE VIEW my_view AS SELECT b,c
> (SELECT a, b FROM table2 WHERE b=1) my_ab,
> (SELECT  c FROM table3, my_ab WHERE table3.a=my_ab.a) my_c;

Something like:

CREATE VIEW my_view AS SELECT table2.b, table3.c   from table2, table3   where     table2.b = 1 and     table2.a =
table3.a;


Re: Problem using Subselect results

From
Josh Berkus
Date:
Oliver,

> CREATE VIEW my_view AS SELECT b,c
> (SELECT a, b FROM table2 WHERE b=1) my_ab,
> (SELECT  c FROM table3, my_ab WHERE table3.a=my_ab.a) my_c;

This isn't possible in PostgreSQL, and I'm not sure it's possible anywhere.  
HOWEVER, if you put your subselects in the FROM clause instead, like so:

CREATE VIEW my_sub AS
SELECT my_ab.a, my_ab.b, my_c.c
FROM (SELECT a, b FROM table2 WHERE b=1) my_ab,(SELECT  a,c FROM table3, my_ab) my_c
WHERE my_ab.a = my_c.a;

OR you can mix-and-match subselect types:

CREATE VIEW my_sub AS
SELECT my_ab.a, my_ab.b,(SELECT  c FROM table3, my_ab WHERE table3.a=my_ab.a) my_c
FROM (SELECT a, b FROM table2 WHERE b=1) my_ab;

Although in the simplistic examples above there's not much reason to use a 
subselect at all, of course.

-- 
Josh Berkus
Aglio Database Solutions
San Francisco


Re: Problem using Subselect results

From
oheinz@stud.fbi.fh-darmstadt.de
Date:
> Although in the simplistic examples above there's not much reason to use a 
> subselect at all, of course.

O.K. my fault - and the subselects,  now that i know not to use them on the 
same level, seem not to be my real problem.

Another (hopefully better) example to show you what I was trying to achieve:

Three tables:

Table 'one' references table 'two', table 'two' references table 'three'

So creating a view which contains the corresponing data would be something 
like: 

CREATE VIEW data AS SELECT two_value, three_value FROM ((one JOIN two ON 
((one.two_id = two.two_id))) JOIN three ON ((two.three_id = three.three_id)));

But as this data is time sensitive, we introduce some kind of time stamp - a 
serial which is global to all tables. Now, for each record in table 'one' i 
want to see only the corresponding records in tables two, three, etc... that 
were created before 'one.updatenr'

SELECT * FROM one, two WHERE (one.two_id=two.two_id AND one.updatenr > 
two.updatenr);

This might match multiple records in tables two (two_id is not a pk, we have 
historic records in this table). Now I want only the most current version 
before one.updatenr. - And that's where I run into trouble. (that's why i 
constructed those awful subselects)

with 'max()' and 'order by updatenr desc limit 1;' I limit results to one 
value  - but I need one maximum for each one_id=two_id
Any ideas on how to do this is in SQL?


Same then with table 'three', it is referenced by table 'two' but updatenr is 
restricted by one.updatenr.


TIA,
Oliver


For those who want to help this is the examples table structure:

-- Sequence: public.updatenr
CREATE SEQUENCE public.updatenr INCREMENT 1 MINVALUE 1 MAXVALUE 
9223372036854775807 CACHE 1;


-- Table: public.one
CREATE TABLE public.one ( one_id int4,  two_id int4,  updatenr int4 DEFAULT nextval('public."updatenr"'::text) NOT
NULL
) WITH OIDS;

-- Table: public.two
CREATE TABLE public.two ( two_id int4 NOT NULL,  two_value varchar(256),  three_id int4 NOT NULL,  updatenr int4
DEFAULTnextval('public."updatenr"'::text) NOT NULL
 
) WITH OIDS;

-- Table: public.three
CREATE TABLE public.three ( three_id int4 NOT NULL,  three_value varchar(256),  updatenr int4 DEFAULT
nextval('public."updatenr"'::text)NOT NULL
 
) WITH OIDS;

-------------------------------------------------
This mail sent through IMP: http://horde.org/imp/


Re: Problem using Subselect results

From
Tom Lane
Date:
oheinz@stud.fbi.fh-darmstadt.de writes:
> But as this data is time sensitive, we introduce some kind of time stamp - a 
> serial which is global to all tables. Now, for each record in table 'one' i 
> want to see only the corresponding records in tables two, three, etc... that 
> were created before 'one.updatenr'

> SELECT * FROM one, two WHERE (one.two_id=two.two_id AND one.updatenr > 
> two.updatenr);

> This might match multiple records in tables two (two_id is not a pk, we have 
> historic records in this table). Now I want only the most current version 
> before one.updatenr. - And that's where I run into trouble.

You might be able to make this work by using SELECT DISTINCT ON.  See
the "weather reports" example in the SELECT reference page.
        regards, tom lane


Re: Problem using Subselect results

From
"Oliver Heinz"
Date:
I'll try this tomorrow - combining DISTINCT ON (two.two_id) and sorting by
two.updatenr could (should) have the desired effect - I never thought about
using ORDER and DISTINCT that way.

I'll report my success or failure...

Thanks so far!

Bye,
Oliver

----- Original Message ----- 
From: "Tom Lane" <tgl@sss.pgh.pa.us>
To: <oheinz@stud.fbi.fh-darmstadt.de>
Cc: <pgsql-sql@postgresql.org>
Sent: Tuesday, July 29, 2003 5:00 PM
Subject: Re: [SQL] Problem using Subselect results


> oheinz@stud.fbi.fh-darmstadt.de writes:
> > But as this data is time sensitive, we introduce some kind of time
stamp - a
> > serial which is global to all tables. Now, for each record in table
'one' i
> > want to see only the corresponding records in tables two, three, etc...
that
> > were created before 'one.updatenr'
>
> > SELECT * FROM one, two WHERE (one.two_id=two.two_id AND one.updatenr >
> > two.updatenr);
>
> > This might match multiple records in tables two (two_id is not a pk, we
have
> > historic records in this table). Now I want only the most current
version
> > before one.updatenr. - And that's where I run into trouble.
>
> You might be able to make this work by using SELECT DISTINCT ON.  See
> the "weather reports" example in the SELECT reference page.
>
> regards, tom lane
>




Re: Problem using Subselect results

From
oheinz@stud.fbi.fh-darmstadt.de
Date:
I did try the following:

SELECT DISTINCT ON (two.two_id) two.two_value FROM one,two WHERE 
(one.two_id=two.two_id 
AND one.updatenr > two.updatenr) ORDER BY two.updatenr ASC;

I thought this would
a) order the result list by updatenr
b) return the first record only for records that are equal on the two.two_id 
field
which would return exactly what I need - return the record with the  

But what I get instead is "ERROR:  SELECT DISTINCT ON expressions must match 
initial ORDER BY expressions" *grrrmpfh*

But after a while playing around I noticed that the "initial" in that sentence 
above is important - adding two.two_id as first argument to the ORDER BY does 
not change the result but fulfill the requirements - the expressions don't have 
to be excactly the same - just the initial argument.

My view which returns the (hopefully) correct results:

SELECT DISTINCT ON (two.two_id) two.two_value FROM one, two WHERE ((one.two_id 
= two.two_id) AND (one.updatenr > two.updatenr)) ORDER BY two.two_id, 
two.updatenr;

Next step is to include corresponding information from table three - now I need 
subselects right? no way around with this DISTINCT and ORDER by stuff in it ...


Many thanks for your help so far,
Oliver



Quoting Oliver Heinz <oheinz@stud.fbi.fh-darmstadt.de>:

> I'll try this tomorrow - combining DISTINCT ON (two.two_id) and sorting by
> two.updatenr could (should) have the desired effect - I never thought about
> using ORDER and DISTINCT that way.
> 
> I'll report my success or failure...
> 
> Thanks so far!
> 
> Bye,
> Oliver


-------------------------------------------------
This mail sent through IMP: http://horde.org/imp/


Re: Problem using Subselect results

From
Josh Berkus
Date:
Oliver,

> SELECT DISTINCT ON (two.two_id) two.two_value FROM one,two WHERE
> (one.two_id=two.two_id
> AND one.updatenr > two.updatenr) ORDER BY two.updatenr ASC;

FWIW, SELECT DISTINCT ON () is slower than SELECT .... ORDER BY ... LIMIT 1 on
all stable versions of Postgres.   Not that the LIMIT 1 method can be used
with all queries.

--
-Josh BerkusAglio Database SolutionsSan Francisco