Получить серию отсчетов с условиями, используя ActiveRecord - PullRequest
0 голосов
/ 25 апреля 2018

Я отображаю график с Subscription подсчетами, которые в какой-то момент могли быть soft_destroyed_at.

Для этого я запускаю запрос для каждого месяца, который, конечно, не так хорош, как одинбольшой гудящий запрос, но мои навыки работы с SQL снова подводят меня.

Вот как я делаю это в Ruby:

months = (0..12).map { |i| i.months.ago.end_of_month }

stats = Hash[months.map do |eom|
  [
    eom.beginning_of_month.to_date,
    Subscription.where(
      'created_at < ?' \
      'AND (soft_destroyed_at IS NULL ' \
      '  OR soft_destroyed_at > ?) ' \
      'AND (suspended_at IS NULL ' \
      '  OR suspended_at > ?)',
      eom, eom, eom
    ).count
  ]
end]

# => { 2018-04-01 => 10, 2018-03-01 => 15, ... }

Как я могу написать это как один запрос, используя ActiveRecord - или, если необходимо, используя raw SQL>

База данных Postgres 10.2, приложение Rails 5.2.

Спасибо!

1 Ответ

0 голосов
/ 28 апреля 2018

Вы можете использовать этот запрос (я использовал 12 месяцев в 2017 году; просто измените, как хотите).Предполагается, что DB Postgresql, как вы сказали в комментарии:

query = 
  "select months.month, count(created_at) "\
  "from "\
    "(select DATE '2017-01-01'+(interval '1' month * generate_series(0,11)) as month, "\
            "DATE '2017-02-01'+(interval '1' month * generate_series(0,11)) as next) months "\
    "outer join subscriptions on "\
    "created_at < month and "\
    "(soft_destroyed_at IS NULL or soft_destroyed_at >= next) and "\
    "(suspended_at IS NULL OR suspended_at >= next) "\
  "group by month "\
  "order by month"

results = ActiveRecord::Base.connection.execute(query)

Первый подзапрос (select внутри from) генерирует это:

month                 next
"2017-01-01 00:00:00";"2017-02-01 00:00:00"
"2017-02-01 00:00:00";"2017-03-01 00:00:00"
"2017-03-01 00:00:00";"2017-04-01 00:00:00"
"2017-04-01 00:00:00";"2017-05-01 00:00:00"
"2017-05-01 00:00:00";"2017-06-01 00:00:00"
"2017-06-01 00:00:00";"2017-07-01 00:00:00"
"2017-07-01 00:00:00";"2017-08-01 00:00:00"
"2017-08-01 00:00:00";"2017-09-01 00:00:00"
"2017-09-01 00:00:00";"2017-10-01 00:00:00"
"2017-10-01 00:00:00";"2017-11-01 00:00:00"
"2017-11-01 00:00:00";"2017-12-01 00:00:00"
"2017-12-01 00:00:00";"2018-01-01 00:00:00"

Next is onlyиспользуется для упрощения проверки, была ли подписка активной по крайней мере до следующего месяца (уничтожены или приостановлены>> next (что гарантирует, что подписчик был активным в течение текущего месяца).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...