X-Original-To: pgsql-sql-postgresql.org@localhost.postgresql.org Received: from localhost (mx1.hub.org [200.46.208.251]) by postgresql.org (Postfix) with ESMTP id 16DB69FA42A for ; Sun, 7 May 2006 05:31:28 -0300 (ADT) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.208.251]) (amavisd-new, port 10024) with ESMTP id 84942-03 for ; Sun, 7 May 2006 05:31:21 -0300 (ADT) X-Greylist: from auto-whitelisted by SQLgrey- Received: from peufeu.com (boutiquenumerique.com [82.67.9.10]) by postgresql.org (Postfix) with ESMTP id 5BAFF9FA32D for ; Sun, 7 May 2006 05:31:20 -0300 (ADT) Received: (qmail 15531 invoked from network); 7 May 2006 10:32:30 +0200 Received: from boutiquenumerique.com (HELO apollo13) (82.67.9.10) by boutiquenumerique.com with SMTP; 7 May 2006 10:32:30 +0200 Date: Sun, 07 May 2006 10:32:29 +0200 To: "Ben K." , =?utf-8?B?TWlyb3NsYXYgxaB1bGM=?= Subject: Re: Most efficient way to hard-sort records Cc: pgsql-sql@postgresql.org References: <445C5A94.4020907@startnet.cz> From: PFC Content-Type: text/plain; format=flowed; delsp=yes; charset=utf-8 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID: In-Reply-To: User-Agent: Opera M2/8.51 (Linux, build 1462) X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200605/76 X-Sequence-Number: 25107 Is it possible to do this : CREATE TABLE sorted (order_no SERIAL PRIMARY KEY, other columns...) INSERT INTO sorted (columns) SELECT * FROM main_table INNER JOIN key_table ON main_table.id = key_table.main_table_id WHERE key = 'param' ORDER BY value SELECT The SERIAL will automatically generate the order_no you want, which corresponds to the position in the sorted set. Then, to get the records in-order : SELECT * FROM sorted ORDER BY order_no As the records have been inserted in-order in the "sorted" table, this table is, in fact, clustered, so a full table scan using the index on "order_no" will be very fast. Of course this is only interesting if this data is quite static, because you'll have to re-generate the table when the data changes. There is another solution : CREATE INDEX on key_table( key, value ) Now, the index can optimize ordering by (key,value), which is equivalent to ordering by value if key = constant. A bit of query manipulation might get you what you want ; I suppose all rows in "key_table" reference a row in "main_table" ; so it is faster to sort (and limit) first on key_table, then grab the rows from main_table : SELECT k.value, m.* FROM key_table k LEFT JOIN main_table m ON m.id=k.main_table_id WHERE k.key='param' ORDER BY k.key, k.value If key_table REFERENCES main_table, LEFT JOIN is equivalent to INNER JOIN ; however if the planner is smart enough, it might notice that it can index-scan key_table in key,value order, grabbing rows from main_table in order and skip the sort entirely. On Sun, 07 May 2006 08:53:46 +0200, Ben K. wrote: >> main_table: id, name, position >> key_table: id, main_table_id, key, value >> >> Here is how I need to sort the records: >> SELECT * FROM main_table >> INNER JOIN key_table ON main_table.id = key_table.main_table_id >> WHERE key = 'param' >> ORDER BY value >> >> I currently collect all ids from main_table in sorted order and then >> update the position field for each row in the main_table one-by-one. Is >> there a better/faster/more efficient solution? > > > A cheap solution if you don't care about the position value as long as > sort order is ok. > > 1) > # SELECT main_table.id into temp_table FROM main_table INNER JOIN > key_table ON main_table.id = key_table.main_table_id ORDER BY value; > > 2) > # update main_table set position = (select oid from temp_table where id > = main_table.id ); > > I guess I'll get a set of consecutive oids by this. > > You can make the number begin at arbitrary number, by > > 2-a) > # update main_table set position = ( (select oid::int4 from temp_table > where id = main_table.id ) - (select min(oid::int4) from temp_table) > + 1) ; > > I read that oid wraps around (after ~ billions) so you might want to > check your current oid. > > > > > Regards, > > Ben K. > Developer > http://benix.tamu.edu > > ---------------------------(end of broadcast)--------------------------- > TIP 5: don't forget to increase your free space map settings