Nie przychodzi mi do głowy żaden czysty sposób na uzyskanie pożądanych wyników za pomocą ActiveRecord, ale w SQL jest to całkiem proste.
Wszystko, co naprawdę próbujesz zrobić, to otworzyć deal_goal
tablice i zbuduj histogram na podstawie otwartych tablic. Możesz to wyrazić bezpośrednio w SQL w ten sposób:
with expanded_deals(id, goal) as (
select id, unnest(deal_goal)
from deals
)
select goal, count(*) n
from expanded_deals
group by goal
A jeśli chcesz uwzględnić wszystkie cztery cele, nawet jeśli nie występują w żadnym z deal_goal
s następnie po prostu wrzuć LEWE DOŁĄCZENIE, aby to powiedzieć:
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
Demo SQL :http://sqlfiddle.com/#!15/3f0af/20
Wrzuć jeden z nich do select_rows
zadzwoń, a otrzymasz swoje dane:
Deal.connection.select_rows(%q{ SQL goes here }).each do |row|
goal = row.first
n = row.last.to_i
#....
end
Prawdopodobnie dzieje się tutaj wiele rzeczy, których nie znasz, więc wyjaśnię trochę.
Przede wszystkim używam WITH i Common Table Expressions (CTE) w celu uproszczenia SELECTów. WITH to standardowa funkcja SQL który umożliwia tworzenie makr SQL lub wbudowanych tabel tymczasowych. W większości przypadków możesz wziąć CTE i upuścić je bezpośrednio w zapytaniu, gdzie jego nazwa to:
with some_cte(colname1, colname2, ...) as ( some_pile_of_complexity )
select * from some_cte
jest tak:
select * from ( some_pile_of_complexity ) as some_cte(colname1, colname2, ...)
CTE to sposób SQL refaktoryzacji nadmiernie złożonego zapytania/metody na mniejsze i łatwiejsze do zrozumienia fragmenty.
unnest
to funkcja tablicowa, która rozpakowuje tablicę na pojedyncze wiersze. Więc jeśli powiesz unnest(ARRAY[1,2])
, otrzymasz dwa wiersze z powrotem:1
i 2
.
WARTOŚCI w PostgreSQL służy mniej więcej do generowania wbudowanych tabel stałych. Możesz użyć VALUES wszędzie tam, gdzie możesz użyć normalnej tabeli, to nie jest tylko jakaś składnia, którą wrzucasz w INSERT, aby powiedzieć bazie danych, jakie wartości wstawić. Oznacza to, że możesz mówić takie rzeczy:
select * from (values (1), (2)) as dt
i pobierz wiersze 1
i 2
na zewnątrz. Wrzucenie tych wartości do CTE sprawia, że wszystko staje się przyjemne i czytelne, a w końcowym zapytaniu wygląda jak każda stara tabela.