Search code examples
postgresqldatetimecommon-table-expressiongenerate-series

How can I get unique fields when building a table using Common Table Expression (CTE) in PostgreSQL?


I'm trying to generate a series of timestamps, calculate the day of the week for each timestamp and select only timestamps that fall Monday - Saturday, using PostGreSQL.

Here's my attempt so far:

WITH
candidates AS (SELECT * FROM generate_series(
  date_trunc('hour', CURRENT_TIMESTAMP - INTERVAL '2 hours'),
  date_trunc('hour', CURRENT_TIMESTAMP - INTERVAL '2 hours')+INTERVAL '1 week',
  INTERVAL '1 hour')),
candidows AS (SELECT EXTRACT(DOW FROM generate_series) FROM candidates),
candidatable AS (SELECT b.date_part AS dow, a.generate_series as start_booking FROM candidates a, candidows b)
SELECT * FROM candidatable WHERE dow != 0;

The view returned includes a dow column which behaves as I expect, but the start_booking column just contains the same value repeated:

 dow |     start_booking
-----+------------------------
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   2 | 2017-09-19 11:00:00+01
   3 | 2017-09-19 11:00:00+01
   3 | 2017-09-19 11:00:00+01
   3 | 2017-09-19 11:00:00+01

If I replace the last SELECT statement with:

SELECT * FROM candidates;

Then the data I'm trying to view as start_booking above are sequential, as I expect:

    generate_series
------------------------
 2017-09-19 11:00:00+01
 2017-09-19 12:00:00+01
 2017-09-19 13:00:00+01
 2017-09-19 14:00:00+01
 2017-09-19 15:00:00+01
 2017-09-19 16:00:00+01

What can I do to get the data from candidates.generate_series to appear as candidatables.start_booking?


Solution

  • a wild guess - are you trying to:

    WITH
    candidates AS (SELECT generate_series start_booking, EXTRACT(DOW FROM generate_series) dow FROM generate_series(
      date_trunc('hour', CURRENT_TIMESTAMP - INTERVAL '2 hours'),
      date_trunc('hour', CURRENT_TIMESTAMP - INTERVAL '2 hours')+INTERVAL '1 week',
      INTERVAL '1 hour'))
    SELECT * FROM candidates WHERE dow != 0;
    

    ?..