Мне нужно сделать немного статистики по использованию приложения. У меня есть 2 модели, которые копят данные:
PullLog
id
user_id
foo_id
bar_id
created_at
RestateLog
id
user_id
foo_id
change_to
created_at
Foo
- has_many pull_logs
- has_many restate_logs
Пользователь
- has_many pull_logs
- has_many restate_logs
Пример данных, которые мне нужно получитьследующие:
- сколько pull_logs сделал пользователь?
- сколько restate_logs сделал пользователь?
Я использую rails 6 и postgresи желательно, чтобы я хотел выразить эти запросы в активной записи
Я предложил 2 запроса:
SELECT
pull_logs.user_id,
count(pull_logs.user_id) as user_pull_logs_count,
count(bar.id) FILTER ( WHERE bar.uuid = 'uuid') as example_bar_count
count(*) FILTER (WHERE pull_logs.bar_id IS NULL) as direct_problems_count
FROM
problem_pull_logs
LEFT JOIN
bar ON pull_logs.bar_id = bar.id
GROUP BY
pull_logs.user_id
Второй оператор SQL:
SELECT
user_id,
COUNT(*) AS restate_count,
COUNT(*) FILTER ( WHERE restate_logs.change_to = 'to_call' ) as to_call_count,
COUNT(*) FILTER ( WHERE restate_logs.change_to = 'success' ) as to_success_count,
COUNT(*) FILTER ( WHERE restate_logs.change_to = 'canceled' ) as to_canceled_count
FROM
restate_logs
GROUP BY
restate_logs.user_id
Есть лиспособ объединить эти 2 запроса?
Я также хотел бы получить такие данные, как:
- сколько pull_logs пользователь сделал за день?
или
- сколько pull_logs сделал пользователь bar_id?
Мне также нужно иметь возможность добавлять фильтры, такие как получение данных. т.е только для данного пользователя или только для данного дня или bar_id
Редактировать: пример данных:
pull_log
id: 1 ; foo_id: 1 ; user_id: 2 ; bar_id: 1 ; created_at: 2019-09-17
id: 2 ; foo_id: 1 ; user_id: 2 ; bar_id: 1 ; created_at: 2019-09-18
id: 3 ; foo_id: 2 ; user_id: 1 ; bar_id: 2 ; created_at: 2019-09-18
restate_log
id: 1 ; foo_id: 1 ; user_id: 2 ; change_to: "to_call" ; created_at: 2019-09-17
id: 2 ; foo_id: 1 ; user_id: 2 ; change_to: "success" ; created_at: 2019-09-18
id: 3 ; foo_id: 2 ; user_id: 1 ; change_to: "to_call" ; created_at: 2019-09-18
Ожидаемые результаты:
user_id 1
pull_count 1
pull_from_bar_1_count 0
pull_from_bar_2_count 1
restate_count 1
restate_to_call_count 1
restate_to_success_count 0
user_id 2
pull_count 2
pull_from_bar_1_count 2
pull_from_bar_2_count 0
restate_count 2
restate_to_call_count 1
restate_to_success_count 1
РЕДАКТИРОВАТЬ:
После ответа от GMB
Я перенес эти два запроса в ActiveRecord следующим образом:
def pull_logs
PullLog.select(<<-SQL.squish
pull_logs.user_id as user_id,
count(pull_logs.user_id) as user_pull_logs_count,
count(foo.id) FILTER (
WHERE foo.uuid = '66ca4921-b66b-47d8-bd75-5c1ac8e92118'
) as foo_1_count,
count(*) FILTER (WHERE pull_logs.foo_id IS NULL)
as direct_count
SQL
).joins(<<-SQL.squish
LEFT JOIN foo
ON pull_logs.foo_id = foo.id
SQL
).group("pull_logs.user_id")
.order("pull_logs.user_id")
end
def restate_logs
RestateLog.select(<<-SQL.squish
restate_logs.user_id,
COUNT(*) AS restate_count,
COUNT(*) FILTER ( WHERE restate_logs.change_to = 'to_call' ) as to_call_count,
COUNT(*) FILTER ( WHERE restate_logs.change_to = 'success' ) as to_success_count,
COUNT(*) FILTER ( WHERE restate_logs.change_to = 'canceled' ) as to_canceled_count
SQL
).group("restate_logs.user_id")
.order("restate_logs.user_id")
end
Я объединяю это2 запроса в
Model.select("*")
.from(<<-SQL.squish
(#{pull_logs}) as pull_logs
LEFT JOIN (#{restate_logs}) as restate_logs
ON pull_logs.user_id = restate_logs.user_id)
SQL
)
Интересно, может ли быть более простой способ объединить результаты, чтобы представить их в виде одной таблицы?