-
-
Notifications
You must be signed in to change notification settings - Fork 16
Join Series
Part 1 of the report
series
This feature produces a join of your main query against a generated_series()
function result. The main motivation behind this feature was the generation of reports. More specifically, reports using created_at
that would originally cause undesired roles in the output. PostgreSQL Docs.
You can disable this feature using config.join_series
.
The join_series
will basically generate a proper join between the generated_series()
PG function, using a Range
as base, and the column provided on the with:
argument.
# SELECT "users".* FROM "users" INNER JOIN GENERATE_SERIES(0::integer, 100::integer) AS series ON "series" = "users"."age"
User.join_series(0..100, with: :age)
The range can be of any type, including dates and times. Here is a list of all options that can be used to configure this operation:
-
with:
The column on theON
clause of the join; -
as:
The name of the generated values; -
step:
The step of the series generation. When using with dates and times, a duration (like1.day
) must be provided; -
mode:
The type of the join to use. Valid values are::inner
forINNER JOIN
,:left
forLEFT OUTER JOIN
,:right
forRIGHT OUTER JOIN
, and:full
forFULL OUTER JOIN
; -
time_zone:
A time zone value or attribute. This extra parameter only works with PostgreSQL >= 16.0. -
{ |series, table| }
When provided with a block, you can customize exactly how theON
clause will be handled.
Here is a full example that will count the number of users created each day for January 2025.
range = Date.new(2025, 1, 1)..Date.new(2025, 1, 31)
User.join_series(range , step: 1.day) do |series, table|
series.pg_cast(:date).eq(table['created_at'].pg_cast(:date))
end.group('series').count
SELECT COUNT(*) AS "count_all", series AS "series"
FROM "users"
INNER JOIN GENERATE_SERIES('2025-01-01 00:00:00'::timestamp, '2025-01-31 00:00:00'::timestamp, 'P1D'::interval) AS series
ON "series"::date = "users"."created_at"::date
GROUP BY series;
Can't find what you're looking for? Add an issue to the issue tracker.