Received: from maia.hub.org (maia-5.hub.org [200.46.204.29]) by mail.postgresql.org (Postfix) with ESMTP id 5A4F9632A19 for ; Fri, 30 Jul 2010 12:58:53 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.29]) (amavisd-maia, port 10024) with ESMTP id 82811-07 for ; Fri, 30 Jul 2010 15:58:46 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mail-pv0-f174.google.com (mail-pv0-f174.google.com [74.125.83.174]) by mail.postgresql.org (Postfix) with ESMTP id B89DE632BC1 for ; Fri, 30 Jul 2010 12:58:45 -0300 (ADT) Received: by pvc7 with SMTP id 7so590025pvc.19 for ; Fri, 30 Jul 2010 08:58:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to :subject:references:mime-version:content-type:content-disposition :in-reply-to:user-agent; bh=wU1dyRPzMwAxAXztQA1Vz9kI4eOIAtsnYkwsQDi6y7w=; b=ELqExIEpBZZyaV/B0q/OUZIRd9PlyHMwOSRsA7IuNXBPK7j5lA5jWql3Q8Zen9Q1TL SOaqoKJTRsZhu/7w6gQMiQtQJ6LMKjgFJ2Zr7r+2NTQQFdOyV5jol0rNegrlo6mgyn/5 InzkjU9d7Hs7JpV6pNGPtc7onqYRvHPJFfbuk= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; b=dESpWkXr6nj9NpSy60t4kduIr9L+1jO8wQ7TyCYhf18swKNWT+G/khP8kfkShpEY5j tAva7u5WN1DK1ppTCncEeErhPRl7KujYvX/+sDzKaK27UNkGZdMXX0qFSsFLE1YGqIHg Wutz36eYAwRsoPlp1D04tfoTBcHhsCkXMjUTk= Received: by 10.142.180.20 with SMTP id c20mr1871115wff.134.1280505524627; Fri, 30 Jul 2010 08:58:44 -0700 (PDT) Received: from eddie (c-67-186-249-122.hsd1.ut.comcast.net [67.186.249.122]) by mx.google.com with ESMTPS id f2sm2721916wfp.11.2010.07.30.08.58.42 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 30 Jul 2010 08:58:43 -0700 (PDT) Message-ID: <4c52f6b3.02b28f0a.02e2.ffff9a9e@mx.google.com> Date: Fri, 30 Jul 2010 09:58:32 -0600 From: Joshua Tolley To: pgsql-sql@postgresql.org Subject: Re: grouping subsets References: <20100722100226.GE10348@a-kretschmer.de> <4C48230D.7030304@archonet.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="5/uDoXvLw7AC5HRs" Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.18 (2008-05-17) X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-0.001 tagged_above=-5 required=5 tests=BAYES_20=-0.001, RCVD_IN_DNSWL_NONE=-0.0001 X-Spam-Level: X-Archive-Number: 201007/126 X-Sequence-Number: 34439 --5/uDoXvLw7AC5HRs Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Thu, Jul 22, 2010 at 11:31:23AM +0000, Tim Landscheidt wrote: > Richard Huxton wrote: >=20 > >>> What I want to get is the values grouped by "subset", where a subset = is a set of rows with identical column until the colum changes. > >>> Is there a way to get >=20 > >>> | 2 | B | > >>> | 4 | C | > >>> | 4 | B | > >>> | 3 | D | >=20 > >>> by SQL only? >=20 > >> I think, the problem is that there are 2 identical groups. I think, you > >> can write a pl/pgsql-proc, selecting all ordered by the date-field and > >> walking through the result to do the grouping, checking if the 2nd > >> column is different from the previous. >=20 > >> With plain SQL it's maybe possible too, but i don't know how ... >=20 > > It should be do-able in 8.4 onwards, look into windowing > > functions. In particular the lag() function: >=20 > > SELECT > > mycode, > > mydate, > > lag(mycode) OVER (ORDER BY mydate) AS prev_code > > FROM > > mytable > > ORDER BY mydate; >=20 > > It should be possible to use that as a subquery with an > > outer query that compares mycode=3Dprev_code to get a run > > length. >=20 > Hmmm. Can the outer query be done without using "WITH > RECURSIVE"? How about this: select a, b, c, d, sum =66rom ( select a, b, c, d, new_partition, sum(e) over (partition by partition_num)=20 from ( select a, b, c, d, e, case when lag(a, 1, null) over (order by d) is null or lag(a, 1, null) over (order by d) !=3D a or lag(b, 1, null) over (order by d) is null or lag(b, 1, null) over (order by d) !=3D b or lag(c, 1, null) over (order by d) is null or lag(c, 1, null) over (order by d) !=3D c then nextval('a') else currval('a') end as partition_num, case when lag(a, 1, null) over (order by d) is null or lag(a, 1, null) over (order by d) !=3D a or lag(b, 1, null) over (order by d) is null or lag(b, 1, null) over (order by d) !=3D b or lag(c, 1, null) over (order by d) is null or lag(c, 1, null) over (order by d) !=3D c then 'T'::boolean else 'f'::boolean end as new_partition from foo ) bar ) baz where new_partition; Here's my test table: 5432 josh@postgres# select * from foo; a | b | c | d | e=20 ---+---+---+------------------------+--- 1 | 9 | 1 | 2007-01-01 00:00:05-07 | 8 9 | 2 | 1 | 2007-01-01 00:00:10-07 | 4 9 | 2 | 1 | 2007-01-01 00:00:15-07 | 6 9 | 2 | 1 | 2007-01-01 00:00:20-07 | 2 6 | 5 | 7 | 2007-01-01 00:00:25-07 | 3 4 | 9 | 0 | 2007-01-01 00:00:30-07 | 0 4 | 9 | 0 | 2007-01-01 00:00:35-07 | 7 5 | 2 | 7 | 2007-01-01 00:01:25-07 | 7 5 | 2 | 7 | 2007-01-01 00:01:30-07 | 7 5 | 2 | 7 | 2007-01-01 00:01:35-07 | 9 5 | 2 | 7 | 2007-01-01 00:01:40-07 | 2 5 | 2 | 7 | 2007-01-01 00:01:45-07 | 5 5 | 2 | 7 | 2007-01-01 00:01:50-07 | 8 5 | 2 | 7 | 2007-01-01 00:01:55-07 | 5 5 | 2 | 7 | 2007-01-01 00:02:00-07 | 9 7 | 8 | 8 | 2007-01-01 00:02:05-07 | 7 7 | 8 | 8 | 2007-01-01 00:02:10-07 | 8 9 | 3 | 0 | 2007-01-01 00:02:15-07 | 0 9 | 3 | 0 | 2007-01-01 00:02:20-07 | 8 9 | 2 | 1 | 2007-01-01 00:02:25-07 | 3 9 | 2 | 1 | 2007-01-01 00:02:30-07 | 3 (21 rows) =2E..and these results... a | b | c | d | sum=20 ---+---+---+------------------------+----- 1 | 9 | 1 | 2007-01-01 00:00:05-07 | 8 9 | 2 | 1 | 2007-01-01 00:00:10-07 | 12 6 | 5 | 7 | 2007-01-01 00:00:25-07 | 3 4 | 9 | 0 | 2007-01-01 00:00:30-07 | 7 5 | 2 | 7 | 2007-01-01 00:01:25-07 | 52 7 | 8 | 8 | 2007-01-01 00:02:05-07 | 15 9 | 3 | 0 | 2007-01-01 00:02:15-07 | 8 9 | 2 | 1 | 2007-01-01 00:02:25-07 | 6 (8 rows) -- Joshua Tolley / eggyknap End Point Corporation http://www.endpoint.com --5/uDoXvLw7AC5HRs Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkxS9qgACgkQRiRfCGf1UMPVqwCgqIzV/T5sh5RTVWvbJbbclJ/a 848AnRiBWqga0ByBqYDxP5ovZ5JdLSRm =CSMB -----END PGP SIGNATURE----- --5/uDoXvLw7AC5HRs--