No puedo pensar en ninguna forma limpia de obtener los resultados que busca a través de ActiveRecord, pero es bastante fácil en SQL.
Todo lo que realmente estás tratando de hacer es abrir el deal_goal
arreglos y construir un histograma basado en los arreglos abiertos. Puede expresar eso directamente en SQL de esta manera:
with expanded_deals(id, goal) as (
select id, unnest(deal_goal)
from deals
)
select goal, count(*) n
from expanded_deals
group by goal
Y si desea incluir los cuatro objetivos incluso si no aparecen en ninguno de los deal_goal
s luego simplemente lance un LEFT JOIN para decirlo:
with
all_goals(goal) as (
values ('traffic'),
('acquisition'),
('branding'),
('qualification')
),
expanded_deals(id, goal) as (
select id, unnest(deal_goal)
from deals
)
select all_goals.goal goal,
count(expanded_deals.id) n
from all_goals
left join expanded_deals using (goal)
group by all_goals.goal
Demostración de SQL :http://sqlfiddle.com/#!15/3f0af/20
Lance uno de esos en un select_rows
llama y te daremos tus datos:
Deal.connection.select_rows(%q{ SQL goes here }).each do |row|
goal = row.first
n = row.last.to_i
#....
end
Probablemente están sucediendo muchas cosas aquí con las que no está familiarizado, así que le explicaré un poco.
En primer lugar, estoy usando WITH y Common Table Expressions (CTE) para simplificar las SELECCIONES. WITH es una característica estándar de SQL que le permite producir macros SQL o tablas temporales en línea de algún tipo. En su mayor parte, puede tomar el CTE y colocarlo directamente en la consulta donde se encuentra su nombre:
with some_cte(colname1, colname2, ...) as ( some_pile_of_complexity )
select * from some_cte
es así:
select * from ( some_pile_of_complexity ) as some_cte(colname1, colname2, ...)
Los CTE son la forma SQL de refactorizar una consulta/método demasiado complejo en piezas más pequeñas y fáciles de entender.
unnest
es una función de matriz que desempaqueta una matriz en filas individuales. Así que si dices unnest(ARRAY[1,2])
, recuperas dos filas:1
y 2
.
VALORES en PostgreSQL se usa para, más o menos, generar tablas constantes en línea. Puede usar VALORES en cualquier lugar donde pueda usar una tabla normal, no es solo una sintaxis que agrega un INSERTAR para decirle a la base de datos qué valores insertar. Eso significa que puedes decir cosas como esta:
select * from (values (1), (2)) as dt
y obtener las filas 1
y 2
afuera. Lanzar esos VALORES en un CTE hace que las cosas sean agradables y legibles y hace que se vea como cualquier tabla antigua en la consulta final.