I have this Postgres query to select all users from the last 30 days and group by count.
@users = User.where('created_at >= ?', last_30_day).count(:order => 'DATE(created_at) ASC', :group => ["DATE(created_at)"])
The problem is that is returning like this
2014-01-15 6
2014-01-13 2
2014-01-09 1
And I would like to get the days with cero results as well like this
2014-01-15 6
2014-01-14 0
2014-01-13 2
2014-01-12 0
2014-01-11 0
2014-01-10 0
2014-01-09 1
Any idea how to do this?
To expound on @mu_is_too_short answer you can do it using generate_series
like so:
SELECT dt.series, COUNT(u.created_at)
FROM users u
RIGHT OUTER JOIN (
SELECT
GENERATE_SERIES( (NOW() - INTERVAL '30 day')::date, NOW()::date, '1 day')::date
AS series
) AS dt
on DATE_TRUNC('month', u.created_at) = dt.series
GROUP BY dt.series
ORDER BY dt.series DESC
Which yields like:
series | count
------------+-------
2014-01-08 | 0
2014-01-07 | 0
2014-01-06 | 0
2014-01-05 | 0
2014-01-04 | 0
2014-01-03 | 0
2014-01-02 | 0
2014-01-01 | 1
2013-12-31 | 0
Futhermore the ActiveRecord syntax for this is quite ugly, your best bet is to write it in the pure SQL above and just retrieve your raw results. Something like:
sql = <<-SQL
SELECT dt.series, COUNT(u.created_at)
FROM users u
RIGHT OUTER JOIN (
SELECT
GENERATE_SERIES( (NOW() - INTERVAL '30 day')::date, NOW()::date, '1 day')::date
AS series
) AS dt
on DATE_TRUNC('month', u.created_at) = dt.series
GROUP BY dt.series
ORDER BY dt.series DESC
SQL
records = User.connection.select_all(sql)
records.each do |record|
puts record['series']
end
Because <<-SQL
is interpolated you can use variables inside to adjust your query.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With