Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h3>Procedural solution with PL/pgSQL</h3> <p>The problem is rather unwieldy for plain SQL with aggregate / windows functions. While looping is typically slower than set-based solutions with plain SQL, a procedural solution with plpgsql can make do with a <strong>single sequential scan</strong> over the table (implicit cursor of a <code>FOR</code> loop) and should be <strong><em>substantially faster in this particular case</em></strong>:</p> <p>Test table:</p> <pre><code>CREATE TEMP TABLE tbl (company text, profession text, year int); INSERT INTO tbl VALUES ('Google', 'Programmer', 2000) ,('Google', 'Sales', 2000) ,('Google', 'Sales', 2001) ,('Google', 'Sales', 2002) ,('Google', 'Sales', 2004) ,('Mozilla', 'Sales', 2002); </code></pre> <p>Function:</p> <pre><code>CREATE OR REPLACE FUNCTION f_periods() RETURNS TABLE (company text, profession text, years int[]) AS $func$ DECLARE r tbl; -- use table type as row variable r0 tbl; BEGIN FOR r IN SELECT * FROM tbl t ORDER BY t.company, t.profession, t.year LOOP IF ( r.company, r.profession, r.year) &lt;&gt; (r0.company, r0.profession, r0.year + 1) THEN -- not true for first row RETURN QUERY SELECT r0.company, r0.profession, years; -- output row years := ARRAY[r.year]; -- start new array ELSE years := years || r.year; -- add to array - year can be NULL, too END IF; r0 := r; -- remember last row END LOOP; RETURN QUERY -- output last iteration SELECT r0.company, r0.profession, years; END $func$ LANGUAGE plpgsql; </code></pre> <p>Call:</p> <pre><code>SELECT * FROM f_periods(); </code></pre> <p>Produces the requested result.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload