Search code examples
sqlpostgresqlpostgresql-9.4generate-seriesset-returning-functions

Get even / odd / all numbers between two numbers


I want to display all the numbers (even / odd / mixed) between two numbers (1-9; 2-10; 11-20) in one (or two) column.
Example initial data:

| rang  |              | r1 | r2 |
--------               -----|-----
| 1-9   |              | 1  | 9  |
| 2-10  |              | 2  | 10 |
| 11-20 |      or      | 11 | 20 |

CREATE TABLE initialtableone(rang TEXT);
INSERT INTO initialtableone(rang) VALUES
  ('1-9'),
  ('2-10'),
  ('11-20');

CREATE TABLE initialtabletwo(r1 NUMERIC, r2 NUMERIC);
INSERT INTO initialtabletwo(r1, r2) VALUES
  ('1', '9'),
  ('2', '10'),
  ('11', '20');

Result:

| output                         |
----------------------------------
| 1,3,5,7,9                      |
| 2,4,6,8,10                     |
| 11,12,13,14,15,16,17,18,19,20  |

Solution

  • Something like this:

    create table ranges (range varchar);
    
    insert into ranges 
    values
    ('1-9'),
    ('2-10'),
    ('11-20');
    
    with bounds as (
      select row_number() over (order by range) as rn,
             range,
             (regexp_split_to_array(range,'-'))[1]::int as start_value,
             (regexp_split_to_array(range,'-'))[2]::int as end_value
      from ranges
    )
    select rn, range, string_agg(i::text, ',' order by i.ordinality)
    from bounds b
      cross join lateral generate_series(b.start_value, b.end_value) with ordinality i
    group by rn, range
    

    This outputs:

    rn | range | string_agg                   
    ---+-------+------------------------------
     3 | 2-10  | 2,3,4,5,6,7,8,9,10           
     1 | 1-9   | 1,2,3,4,5,6,7,8,9            
     2 | 11-20 | 11,12,13,14,15,16,17,18,19,20