Received: from maia.hub.org (maia-3.hub.org [200.46.204.243]) by mail.postgresql.org (Postfix) with ESMTP id 824EB1337C2E for ; Wed, 17 Nov 2010 12:02:53 -0400 (AST) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.243]) (amavisd-maia, port 10024) with ESMTP id 68745-07 for ; Wed, 17 Nov 2010 16:02:46 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from vs137086.vserver.de (static-ip-62-75-137-86.inaddr.intergenia.de [62.75.137.86]) by mail.postgresql.org (Postfix) with ESMTP id 18FBA1337BD7 for ; Wed, 17 Nov 2010 12:02:18 -0400 (AST) Received: (qmail 10006 invoked from network); 17 Nov 2010 17:02:18 +0100 Received: from p57aad14a.dip.t-dialin.net (HELO a-kretschmer.de) (87.170.209.74) by static-ip-62-75-137-86.inaddr.intergenia.de with (AES256-SHA encrypted) SMTP; 17 Nov 2010 17:02:18 +0100 Received: from kretschmer by a-kretschmer.de with local (Exim 4.69) (envelope-from ) id 1PIkSe-00008D-Ib for pgsql-sql@postgresql.org; Wed, 17 Nov 2010 17:02:16 +0100 Date: Wed, 17 Nov 2010 17:02:16 +0100 From: Andreas Kretschmer To: pgsql-sql@postgresql.org Subject: Re: obtaining difference between minimum value and next in size Message-ID: <20101117160216.GA32573@tux> References: <3BC753A3784F488F98304300B6E437FD@squarepi.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <3BC753A3784F488F98304300B6E437FD@squarepi.com> X-OS: Debian/GNU Linux - weil ich es mir Wert bin! X-GPG-Fingerprint: EE16 3C01 7B9C 10F7 2C8B 3B86 4DB3 D9EE 7F45 84DA X-Message-Flag: "Windows" is not the answer. "Windows" is the question and the answer is "no"! X-Lugdd: Gerd Kube X-Info: My name is root. Just root. And I am licensed to kill -9 User-Agent: Mutt/1.5.18 (2008-05-17) X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-1.9 tagged_above=-5 required=5 tests=BAYES_00=-1.9 X-Spam-Level: X-Archive-Number: 201011/38 X-Sequence-Number: 34776 John Lister wrote: > Hi, I was wondering if it is possible to do this with a single query rather > than iterate over all of the rows in an application: > > I have a table which for brevity looks like: > create table offers { > integer id; > integer product_id; > double price; > } > > where for each product there is a number of offers in this table. Now my > question: > Is it possible to obtain the difference between just the minimum price and the > next one up per product, so say I have the following data: > id, product_id, price > 123, 2, 10.01 > 125, 2, 10.05 > 128, 2, 11.30 > 134, 3, 9.45 > 147, 3, 11.42 > 157, 3, 12.08 > 167, 3, 12.09 > > then I would like the following returned > product_id, difference > 2, .04 (10.05-10.01) > 3, 1.97 (11.42-9.45) > > ,etc > > > Any ideas? Sure, as Tom Lane pointed out, with >= 8.4: test=*# select * from offers ; id | product_id | price -----+------------+------- 123 | 2 | 10.01 125 | 2 | 10.05 128 | 2 | 11.30 134 | 3 | 9.45 147 | 3 | 11.42 157 | 3 | 12.08 167 | 3 | 12.09 (7 Zeilen) Zeit: 0,204 ms test=*# select product_id, price, price - lag(price) over (partition by product_id order by product_id, price), row_number() over (partition by product_id)from offers; product_id | price | ?column? | row_number ------------+-------+----------+------------ 2 | 10.01 | | 1 2 | 10.05 | 0.04 | 2 2 | 11.30 | 1.25 | 3 3 | 9.45 | | 1 3 | 11.42 | 1.97 | 2 3 | 12.08 | 0.66 | 3 3 | 12.09 | 0.01 | 4 (7 Zeilen) Zeit: 0,415 ms test=*# select product_id, price, difference from (select product_id, price, price - lag(price) over (partition by product_id order by product_id, price) as difference, row_number() over (partition by product_id) from offers) foo where row_number <= 2; product_id | price | difference ------------+-------+------------ 2 | 10.01 | 2 | 10.05 | 0.04 3 | 9.45 | 3 | 11.42 | 1.97 (4 Zeilen) Andreas -- Really, I'm not out to destroy Microsoft. That will just be a completely unintentional side effect. (Linus Torvalds) "If I was god, I would recompile penguin with --enable-fly." (unknown) Kaufbach, Saxony, Germany, Europe. N 51.05082°, E 13.56889°