Nenapadá mě žádný čistý způsob, jak prostřednictvím ActiveRecord získat výsledky, o které usilujete, ale v SQL je to docela snadné.
Jediné, o co se skutečně snažíte, je otevřít deal_goal
pole a vytvořte histogram založený na otevřených polích. Můžete to vyjádřit přímo v SQL takto:
with expanded_deals(id, goal) as (
select id, unnest(deal_goal)
from deals
)
select goal, count(*) n
from expanded_deals
group by goal
A pokud chcete zahrnout všechny čtyři cíle, i když se neobjevují v žádném z deal_goal
s pak stačí hodit LEVÝ JOIN a říct:
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
Ukázka SQL :http://sqlfiddle.com/#!15/3f0af/20
Vhoďte jeden z nich do select_rows
zavolejte a dostanete svá data:
Deal.connection.select_rows(%q{ SQL goes here }).each do |row|
goal = row.first
n = row.last.to_i
#....
end
Pravděpodobně se zde děje mnoho, s čím nejste obeznámeni, takže vám to trochu vysvětlím.
Za prvé, používám WITH a Common Table Expressions (CTE) pro zjednodušení SELECTů. WITH je standardní funkce SQL který vám umožňuje vytvářet SQL makra nebo vložené dočasné tabulky určitého druhu. Z velké části můžete vzít CTE a umístit jej přímo do dotazu, kde je jeho název:
with some_cte(colname1, colname2, ...) as ( some_pile_of_complexity )
select * from some_cte
je takto:
select * from ( some_pile_of_complexity ) as some_cte(colname1, colname2, ...)
CTE představují způsob SQL refaktoringu příliš složitého dotazu/metody na menší a snáze srozumitelné části.
unnest
je funkce pole, která rozbalí pole do jednotlivých řádků. Pokud tedy řeknete unnest(ARRAY[1,2])
, dostanete dva řádky zpět:1
a 2
.
VALUES v PostgreSQL se víceméně používá ke generování vkládaných tabulek konstant. VALUES můžete použít kdekoli, kde byste mohli použít normální tabulku, není to jen nějaká syntaxe, kterou vložíte INSERT, abyste databázi řekli, jaké hodnoty má vložit. To znamená, že můžete říkat věci jako:
select * from (values (1), (2)) as dt
a získat řádky 1
a 2
ven. Vložením těchto HODNOT do CTE jsou věci pěkné a čitelné a v konečném dotazu to vypadá jako jakákoli stará tabulka.