Thread: [SQL] Tricky -to me!- SQL query.

[SQL] Tricky -to me!- SQL query.

From
stuart@ludwig.ucl.ac.uk (Stuart Rison)
Date:
Dear All,

Consider the following table:

dev_brecard=> select * from test order by person;
person|fruit
------+---------
lucy  |mandarins
lucy  |tomatoes
lucy  |pears
lucy  |oranges
lucy  |apples
peter |pears
peter |apples
peter |oranges
peter |prunes
robert|figs
robert|dates
stuart|apples
stuart|pears
stuart|prunes
stuart|bananas
stuart|kumquats
(16 rows)

(code for creating and populating table is in a PS at the end of this posting)

You can assume that the table is appropriately normalised and that there is
a composite primary key for it (i.e. each COMBINATION of person and fruit
will appear only once and neither of the fields can be NULL)

How do I select from all person who like 'pears' and 'apples' (in this
case, lucy, peter and stuart) or 'pears', 'apples' and 'oranges' (in this
case, lucy and peter)?

I re-read my SQL books but I am still somewhat stumped.  Things I could
think of for that sort of query:

1) Select all persons who like 'pears'; Select all persons who like
'apples'; Select all persons who like 'oranges'; Calculate the INTERSECTION
of these sets (this sort of operation appears to use the EXISTS operator?)

2) Use nested subselects:

Select person from test where person in (
        Select person from test where fruit='pears' and person in (
                Select person from test where fruit='apples' and person in (
                        Select person from test where fruit='oranges'
                )
        )
)

What way do you suggest????

Also, am I storing this sort of data in to wrong kind of form (should I
somehow denormalise?  if so, how?)?

Could you please cc your answers to: stuart@ludwig.ucl.ac.uk

thanks for any help out there!

regards,

Stuart.

PS.  Code to cut and paste for table:

create table test (person    varchar(25), fruit     varchar(25));
insert into test values ('stuart','apples');
insert into test values ('stuart','pears');
insert into test values ('stuart','bananas');
insert into test values ('stuart','kumquats');
insert into test values ('peter','oranges');
insert into test values ('peter','prunes');
insert into test values ('lucy','mandarins');
insert into test values ('lucy','tomatoes');
insert into test values ('peter','apples');
insert into test values ('lucy','apples');
insert into test values ('peter','pears');
insert into test values ('lucy','pears');
insert into test values ('lucy','oranges');
insert into test values ('stuart','prunes');
insert into test values ('robert','figs');
insert into test values ('robert','dates');

+-------------------------+--------------------------------------+
| Stuart Rison            | Ludwig Institute for Cancer Research |
+-------------------------+ 91 Riding House Street               |
| Tel. (0171) 878 4041    | London, W1P 8BT, UNITED KINGDOM.     |
| Fax. (0171) 878 4040    | stuart@ludwig.ucl.ac.uk              |
+-------------------------+--------------------------------------+



Re: [SQL] Tricky -to me!- SQL query.

From
Remigiusz Sokolowski
Date:
>
> Consider the following table:
> dev_brecard=> select * from test order by person;
> person|fruit
> ------+---------
> lucy  |mandarins
> lucy  |tomatoes
> lucy  |pears
> lucy  |oranges
> lucy  |apples
> peter |pears
> peter |apples
> peter |oranges
> peter |prunes
> robert|figs
> robert|dates
> stuart|apples
> stuart|pears
> stuart|prunes
> stuart|bananas
> stuart|kumquats
> (16 rows)
>
> (code for creating and populating table is in a PS at the end of this posting)
>
> You can assume that the table is appropriately normalised and that there is
> a composite primary key for it (i.e. each COMBINATION of person and fruit
> will appear only once and neither of the fields can be NULL)
>
> How do I select from all person who like 'pears' and 'apples' (in this
> case, lucy, peter and stuart) or 'pears', 'apples' and 'oranges' (in this
> case, lucy and peter)?

What about:
SELECT person FROM test WHERE fruit='pears' AND fruit='apples' AND
fruit='oranges';
or just
SELECT person FROM test WHERE fruit IN ('pears', 'apples','oranges');

For me strange question - so I think I don't mean exactly what you do ;-)
Could You explain for what You wanna this?
    Rem

-------------------------------------------------------------------*------------
Remigiusz Sokolowski      e-mail: rems@gdansk.sprint.pl           * *
-----------------------------------------------------------------*****----------


Re: [SQL] Tricky -to me!- SQL query.

From
stuart@ludwig.ucl.ac.uk (Stuart Rison)
Date:
>> Stuart wrote:
>>
>> Consider the following table:
>> dev_brecard=> select * from test order by person;
>> person|fruit
>> ------+---------
>> lucy  |mandarins
>> lucy  |tomatoes
>> lucy  |pears
>> lucy  |oranges
>> lucy  |apples
>> peter |pears
>> peter |apples
>> peter |oranges
>> peter |prunes
>> robert|figs
>> robert|dates
>> stuart|apples
>> stuart|pears
>> stuart|prunes
>> stuart|bananas
>> stuart|kumquats
>> (16 rows)
>>
>> (code for creating and populating table is in a PS at the end of this
>>posting)
>>
>> You can assume that the table is appropriately normalised and that there is
>> a composite primary key for it (i.e. each COMBINATION of person and fruit
>> will appear only once and neither of the fields can be NULL)
>>
>> How do I select from all person who like 'pears' and 'apples' (in this
>> case, lucy, peter and stuart) or 'pears', 'apples' and 'oranges' (in this
>> case, lucy and peter)?
>
> Remigiusz answered:
>
>What about:
>SELECT person FROM test WHERE fruit='pears' AND fruit='apples' AND
>fruit='oranges';
>or just
>SELECT person FROM test WHERE fruit IN ('pears', 'apples','oranges');
>
>For me strange question - so I think I don't mean exactly what you do ;-)

Hello Rem,

Yes, there is a misunderstanding here, sorry about that, could be my posting.

The first solution would return an empty table because there are no cases
where fruit can be equal to two different things (the data in fruit are
atomic so the field fruit can only ever be equal to one thing).

The second of solutions answers the question "Who eats pears or eats apples
or eats oranges?" but not the question "Who eats pears AND apples AND
oranges?" (i.e. it would give the answers lucy, peter and stuart when the
actual answers should be lucy and peter because, in the example table,
stuart does not eat oranges).

>Could You explain for what You wanna this?

Hope this is clearer.

regards,

Stuart.

PS.  Of course I actually quite like oranges ;)

+-------------------------+--------------------------------------+
| Stuart Rison            | Ludwig Institute for Cancer Research |
+-------------------------+ 91 Riding House Street               |
| Tel. (0171) 878 4041    | London, W1P 8BT, UNITED KINGDOM.     |
| Fax. (0171) 878 4040    | stuart@ludwig.ucl.ac.uk              |
+-------------------------+--------------------------------------+



Re: [SQL] Tricky -to me!- SQL query.

From
Remigiusz Sokolowski
Date:
> >
> >What about:
> >SELECT person FROM test WHERE fruit='pears' AND fruit='apples' AND
> >fruit='oranges';
> >or just
> >SELECT person FROM test WHERE fruit IN ('pears', 'apples','oranges');
> >
> >For me strange question - so I think I don't mean exactly what you do ;-)
>
> Hello Rem,
>
> Yes, there is a misunderstanding here, sorry about that, could be my posting.
> The first solution would return an empty table because there are no cases
> where fruit can be equal to two different things (the data in fruit are
> atomic so the field fruit can only ever be equal to one thing).
>
> The second of solutions answers the question "Who eats pears or eats apples
> or eats oranges?" but not the question "Who eats pears AND apples AND
> oranges?" (i.e. it would give the answers lucy, peter and stuart when the
> actual answers should be lucy and peter because, in the example table,
> stuart does not eat oranges).
>
Oh, no... I apologize for that - is here to hot or smth.
I must be ill - when I wrote fruit='smth' and fruit='smth_else' - it
couldn't be solution for that.
You're absolutely right.
It needs nested queries or function(which also should realize some
queries)
    Rem

-------------------------------------------------------------------*------------
Remigiusz Sokolowski      e-mail: rems@gdansk.sprint.pl           * *
-----------------------------------------------------------------*****----------


Re: [SQL] Tricky -to me!- SQL query.

From
jwieck@debis.com (Jan Wieck)
Date:
Stuart Rison wrote:

>
> >> Stuart wrote:
> >>
> >> Consider the following table:
> >> dev_brecard=> select * from test order by person;
> >> person|fruit
> >> ------+---------
> >> lucy  |mandarins
> >> [...]
> >>
> >> How do I select from all person who like 'pears' and 'apples' (in this
> >> case, lucy, peter and stuart) or 'pears', 'apples' and 'oranges' (in this
> >> case, lucy and peter)?
> >
> > Remigiusz answered:
> >
> >What about:
> >[...]
>
> The second of solutions answers the question "Who eats pears or eats apples
> or eats oranges?" but not the question "Who eats pears AND apples AND
> oranges?" (i.e. it would give the answers lucy, peter and stuart when the
> actual answers should be lucy and peter because, in the example table,
> stuart does not eat oranges).
>
> >Could You explain for what You wanna this?
>
> Hope this is clearer.

    This one works:

    pgsql=> SELECT DISTINCT person FROM test t1
    pgsql-> WHERE 3 = (SELECT count(*) FROM test t2
    pgsql->    WHERE t2.person = t1.person
    pgsql->    AND t2.fruit IN ('pears', 'apples', 'oranges'));
    person
    ------
    lucy
    peter
    (2 rows)

    pgsql=> SELECT DISTINCT person FROM test t1
    pgsql-> WHERE 2 = (SELECT count(*) FROM test t2
    pgsql->    WHERE t2.person = t1.person
    pgsql->    AND t2.fruit IN ('pears', 'apples'));
    person
    ------
    lucy
    peter
    stuart
    (3 rows)


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#======================================== jwieck@debis.com (Jan Wieck) #