2008/5/14 Karsten Hilbert <[EMAIL PROTECTED]>:

> Hi all,
>
> let's assume I want to select cities by name fragment:
>
>        select * from dem.urb where name ilike 'Lei%';
>
> Then, let's assume I know the zip code and want to use that
> for limiting the range of cities returned:
>
>        select * from dem.urb where
>                name ilike 'Lei%' and
>                zip = '04317'
>        ;
>
> Now, let's assume I have a widget which suggests cities
> based on the typed fragment. Another widget will already got
> the zip code and has it communicated to the city search
> field. So I want to suggest a list of cities which a) have
> the fragment and the zip code  and b) have the fragment. But
> the user may have entered the wrong zip code, so include the
> cities which have just the fragment, too:
>
>        select * from (
>
>                select * from dem.urb where
>                        name ilike 'Lei%' and
>                        zip = '04317'
>
>                union all               -- avoid distinctness at this level
>
>                select * from dem.urb where name ilike 'Lei%'
>
>        );
>
> However, I want those ordered by name:
>
>        select * from (
>
>                select * from dem.urb where
>                        name ilike 'Lei%' and
>                        zip = '04317'
>
>                union all               -- avoid distinctness at this level
>
>                select * from dem.urb where name ilike 'Lei%'
>
>        )
>        order by name;
>
> Then, I also want the ones with the zip code listed at the
> top of the list because they are more likely to be the ones
> (after all we already have the zip code !):
>
>        select * from (
>
>                select *, 1 as rank from dem.urb where
>                        name ilike 'Lei%' and
>                        zip = '04317'
>
>                union all               -- avoid distinctness at this level
>
>                select *, 2 as rank from dem.urb where name ilike 'Lei%'
>
>        )
>        order by rank, name;
>
> This is fine. One nuisance remains: Cities which match both
> zip and name are (of course) listed twice. To eliminate
> duplicates:
>
>        select distinct on (name) * from (
>
>                select *, 1 as rank from dem.urb where
>                        name ilike 'Lei%' and
>                        zip = '04317'
>
>                union all               -- avoid distinctness at this level
>
>                select *, 2 as rank from dem.urb where name ilike 'Lei%'
>
>        ) as inner_union
>
>        order by rank, name;
>
> This sayeth (as it should):
>
>        ERROR:  SELECT DISTINCT ON expressions must match initial ORDER BY
> expressions
>
> Modifying to:
>
>        select * from (
>
>                select distinct on (name) * from (
>
>                        select *, 1 as rank from dem.urb where
>                                name ilike 'Lei%' and
>                                zip = '04317'
>
>                        union all               -- avoid distinctness at
> this level
>
>                        select *, 2 as rank from dem.urb where name ilike
> 'Lei%'
>
>                ) as inner_union
>
>        ) as unique_union
>
>        order by rank, name;
>
> This works. However, one nuisance remains: Because the
> distinct happens before the order by rank it is happenstance
> whether rank 1 cities (with zip) will be listed on top
> anymore.
>
> Effectively I want known-zip cities first, then
> fragment-matching cities but without those already in the
> known-zip list.
>
> Can anyone teach me how I need to do this in SQL ?
>
> Do I really have to explicitely EXCEPT out the first list
> from the second sub query in the union ?
>
> Thanks,
> Karsten
> --
> GPG key ID E4071346 @ wwwkeys.pgp.net
> E167 67FD A291 2BEA 73BD  4537 78B9 A9F9 E407 1346
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>



select * from (
               select *, 1 as rank from dem.urb where
                       name ilike 'Lei%' and
                       zip = '04317'
               union               -- avoid distinctness at this level
               select *, 2 as rank from dem.urb where name ilike 'Lei%'
       )
       order by rank, name;

-- 
Kind Regards,
Mian

Reply via email to