X-Original-To: pgsql-sql-postgresql.org@localhost.postgresql.org Received: from localhost (unknown [200.46.204.144]) by svr1.postgresql.org (Postfix) with ESMTP id 80FC48B9F43 for ; Fri, 4 Feb 2005 21:18:48 +0000 (GMT) Received: from svr1.postgresql.org ([200.46.204.71]) by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024) with ESMTP id 47553-06 for ; Fri, 4 Feb 2005 21:18:36 +0000 (GMT) Received: from wproxy.gmail.com (wproxy.gmail.com [64.233.184.195]) by svr1.postgresql.org (Postfix) with ESMTP id 423398B9E7F for ; Fri, 4 Feb 2005 21:18:37 +0000 (GMT) Received: by wproxy.gmail.com with SMTP id 67so563737wri for ; Fri, 04 Feb 2005 13:18:37 -0800 (PST) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:message-id:date:from:reply-to:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:references; b=dCaMFup/TqEc0mKymkBpzgeY28+8MgVVbMdXLXweIj+NTMbkVqLImBwMg3iMs1ERgszDIsvvVJtcwxjcBHyKdidHt+CSAY3mJNh9mdCeJ2AaIimMw8rKnMiOmswJ5NywgQTFeF5jViZ0UuIMaYQpPUPZ7CCa0fg8SKWWc+x5blc= Received: by 10.54.49.32 with SMTP id w32mr166721wrw; Fri, 04 Feb 2005 13:18:37 -0800 (PST) Received: by 10.54.4.71 with HTTP; Fri, 4 Feb 2005 13:18:37 -0800 (PST) Message-ID: <6c21003b05020413186eb2d41f@mail.gmail.com> Date: Fri, 4 Feb 2005 15:18:37 -0600 From: Don Drake Reply-To: Don Drake To: Michael Glaesemann Subject: Re: Determining Rank Cc: pgsql-sql@postgresql.org In-Reply-To: Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit References: <6c21003b05020319061f8bce45@mail.gmail.com> X-Virus-Scanned: by amavisd-new at hub.org X-Spam-Status: No, hits=0.024 tagged_above=0 required=5 tests=RCVD_BY_IP X-Spam-Level: X-Archive-Number: 200502/91 X-Sequence-Number: 20202 Michael, That's an excellent solution, but on my table, the explain plan sucks and the query time is over 3 minutes when implemented. Is there a simple way to get a row_num without using a temporary sequence? Thanks for your help. -Don On Fri, 4 Feb 2005 14:02:20 +0900, Michael Glaesemann wrote: > > On Feb 4, 2005, at 12:06, Don Drake wrote: > > > I have a query that shows the top N count(*)'s. > > > > So it's basically: > > > > select some_val, count(*) > > from big_table > > group by some_val > > order by count(*) > > limit 50 > > > > Now, I would like to have the rank included in the result set. The > > first row would be 1, followed by 2, etc. all the way to 50. > > There are a couple of different ways to go about this. One is just to > append an extra column that's basically a line number, but I find it > doesn't handle ties very elegantly. The following example uses a > correlated subquery using HAVING to determine the rank as "the number > of items that have a total quantity greater than the current item + 1". > Note that items bar and baz have exactly the same totals and are tied, > while the rank of bat shows that there are 3 items that have totals > greater than bat. > > Joe Celko's "SQL for Smarties" has a bunch of things like this in it. > I've found it quite helpful. > > Hope this helps. > > Michael Glaesemann > grzm myrealbox com > > create table items ( > item text not null > , qty integer not null > ) without oids; > > insert into items (item, qty) values ('foo', 1); > insert into items (item, qty) values ('foo', 2); > insert into items (item, qty) values ('foo', 1); > insert into items (item, qty) values ('foo', 3); > insert into items (item, qty) values ('foo', 3); > insert into items (item, qty) values ('foo', 20); > insert into items (item, qty) values ('foo', 1); > insert into items (item, qty) values ('bar', 3); > insert into items (item, qty) values ('bar', 1); > insert into items (item, qty) values ('bar', 3); > insert into items (item, qty) values ('bar', 13); > insert into items (item, qty) values ('baz', 2); > insert into items (item, qty) values ('baz', 4); > insert into items (item, qty) values ('baz', 14); > insert into items (item, qty) values ('bat', 3); > insert into items (item, qty) values ('bat', 4); > > select item, sum(qty) as tot_qty > from items > group by item > order by tot_qty desc; > > item | tot_qty > ------+--------- > foo | 31 > bar | 20 > baz | 20 > bat | 7 > (4 rows) > > select i1.item > , i1.tot_qty > , ( select count(*) > from ( > select item > , sum(qty) as tot_qty > from items > group by item > having sum(qty) > i1.tot_qty > ) as i2 > ) + 1 as rank > from ( > select item > , sum(qty) as tot_qty > from items > group by item > ) as i1 > order by i1.tot_qty desc; > > item | tot_qty | rank > ------+---------+------ > foo | 31 | 1 > bar | 20 | 2 > baz | 20 | 2 > bat | 7 | 4 > (4 rows) > > -- Donald Drake President Drake Consulting http://www.drakeconsult.com/ http://www.MailLaunder.com/ 312-560-1574