Re: Finding nearest numeric value

From: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
To: Bruno Wolff III <bruno(at)wolff(dot)to>
Cc: Richard Huxton <dev(at)archonet(dot)com>, Poul Møller Hansen <freebsd(at)pbnet(dot)dk>, Postgres general mailing list <pgsql-general(at)postgresql(dot)org>
Subject: Re: Finding nearest numeric value
Date: 2005-08-17 16:10:56
Message-ID: 1124295056.24337.111.camel@coppola.muc.ecircle.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Yep, you're right. The following works and uses the index on pk_col:

prepare test_01 (bigint) as
select * from
(
(SELECT * FROM big_table WHERE pk_col > $1 ORDER BY pk_col LIMIT 1)
UNION ALL
(SELECT * FROM big_table WHERE pk_col < $1 ORDER BY pk_col DESC
LIMIT 1)
) as nearest
order by abs(pk_col - $1)
limit 1;

db=> explain execute test_01(12321);

QUERY
PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=2.12..2.12 rows=1 width=112)
-> Sort (cost=2.12..2.13 rows=2 width=112)
Sort Key: abs((pk_col - $1))
-> Subquery Scan nearest (cost=0.00..2.11 rows=2 width=112)
-> Append (cost=0.00..2.08 rows=2 width=59)
-> Subquery Scan "*SELECT* 1" (cost=0.00..1.04
rows=1 width=59)
-> Limit (cost=0.00..1.03 rows=1 width=59)
-> Index Scan using idx_pk_col on
big_table (cost=0.00..36639172.72 rows=35532914 width=59)
Index Cond: (pk_col > $1)
-> Subquery Scan "*SELECT* 2" (cost=0.00..1.04
rows=1 width=59)
-> Limit (cost=0.00..1.03 rows=1 width=59)
-> Index Scan Backward using
idx_pk_col on big_table (cost=0.00..36639172.72 rows=35532914 width=59)
Index Cond: (pk_col < $1)
(13 rows)

Cheers,
Csaba.

On Wed, 2005-08-17 at 17:57, Bruno Wolff III wrote:
> On Wed, Aug 17, 2005 at 17:35:37 +0200,
> Csaba Nagy <nagy(at)ecircle-ag(dot)com> wrote:
> > The only problem is that you can't use the order by/limit syntax inside
> > the union queries I guess, cause the query you proposed is giving a
> > syntax error. I also thought first to do it like this, but it won't
> > work. If it would, then you could wrap the thing in another query which
> > orders by the difference and limits to the first one ;-)
>
> You probably can just add parenthesis. I think that the second ORDER BY
> and LIMIT may be being applied to the UNION results which would be a
> problem. Putting the second subquery in parens will take care of this if
> that is the problem.
>
> >
> > On Wed, 2005-08-17 at 17:10, Richard Huxton wrote:
> > > Poul Møller Hansen wrote:
> > > > Does anyone know how to find the row with the nearest numeric value, not
> > > > necessarily an exact match ?
> > >
> > > While the other answers all do their job, and in one go too, I'd be
> > > surprised if you found anything faster than:
> > >
> > > SELECT myval FROM mytable WHERE myval > 1234 ORDER BY myval LIMIT 1
> > > UNION ALL
> > > SELECT myval FROM mytable WHERE myval < 1234 ORDER BY myval DESC LIMIT 1
> > >
> > > That gives you (up to) two values to look at, but should use any index
> > > you have on myval.
> > >
> > > You can always sort the results by abs(myval) then if you don't want to
> > > handle two values in the application layer.

In response to

Browse pgsql-general by date

  From Date Subject
Next Message Sebastian Hennebrueder 2005-08-17 16:47:33 Technical FAQ collecting of infos from the mailing list
Previous Message eu 2005-08-17 16:05:36 PostgreSQL 8.0.3 limiting max_connections to 64 ?