Non riesco a pensare a un modo pulito per ottenere i risultati che cerchi tramite ActiveRecord, ma è abbastanza semplice in SQL.
Tutto quello che stai veramente cercando di fare è aprire il deal_goal
array e costruire un istogramma basato sugli array aperti. Puoi esprimerlo direttamente in SQL in questo modo:
with expanded_deals(id, goal) as (
select id, unnest(deal_goal)
from deals
)
select goal, count(*) n
from expanded_deals
group by goal
E se vuoi includere tutti e quattro gli obiettivi anche se non compaiono in nessuno dei deal_goal
s quindi inserisci un LEFT JOIN per dirlo:
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
Dimostrazione SQL :http://sqlfiddle.com/#!15/3f0af/20
Getta uno di questi in un select_rows
chiama e avrai i tuoi dati:
Deal.connection.select_rows(%q{ SQL goes here }).each do |row|
goal = row.first
n = row.last.to_i
#....
end
Probabilmente stanno succedendo molte cose che non conosci, quindi ti spiego un po'.
Prima di tutto, sto usando WITH e Common Table Expressions (CTE) per semplificare i SELECT. CON è una funzionalità SQL standard che ti consente di produrre macro SQL o tabelle temporanee inline di un tipo. Per la maggior parte, puoi prendere il CTE e rilasciarlo direttamente nella query in cui il suo nome è:
with some_cte(colname1, colname2, ...) as ( some_pile_of_complexity )
select * from some_cte
è così:
select * from ( some_pile_of_complexity ) as some_cte(colname1, colname2, ...)
I CTE sono il modo SQL di refactoring di una query/metodo eccessivamente complesso in parti più piccole e di più facile comprensione.
unnest
è una funzione array che decomprime un array in singole righe. Quindi, se dici unnest(ARRAY[1,2])
, ottieni due righe indietro:1
e 2
.
VALORI in PostgreSQL è usato, più o meno, per generare tabelle costanti inline. Puoi usare VALUES ovunque tu possa usare una tabella normale, non è solo una sintassi che inserisci in un INSERT per dire al database quali valori inserire. Ciò significa che puoi dire cose come questa:
select * from (values (1), (2)) as dt
e ottieni le righe 1
e 2
fuori. Lanciare quei VALUES in un CTE rende le cose piacevoli e leggibili e lo fa sembrare una qualsiasi vecchia tabella nella query finale.