计算Active Admin仪表板(Rails,Active admin 1.0,Postgresql数据库,postgres_ext gem)中序列化属性(数组)中值的出现次数

我想要一个基本表来总结数组中值的出现次数。

我的应用程序是一个每日交易应用程序,旨在了解更多Ruby on Rails。

我有一个模型交易,它有一个名为Deal_goal的属性。 它是一个在数组中序列化的多重选择。

这是来自schema.db的deal_goal:

t.string "deal_goal",:array => true 

在此处输入图像描述

所以交易A可以有交易=目标= [交通,资格]和另一笔交易可以有deal_goal = [品牌,交通,收购]

我想要构建的是我的仪表板中的一个表,它将采用每种类型的目标(数组中的每个值)并计算其deal_goal的数组将包含此类目标并计算它们的交易数。

我的目标是拥有这张桌子:

在此处输入图像描述

我怎样才能做到这一点? 我想我需要为每种类型的值对每个deal_goal数组进行分组,然后计算这些目标在数组中出现的次数。 我对RoR很新,无法做到。

这是我到目前为止的代码:

 column do panel "top of Goals" do table_for Deal.limit(10) do column ("Goal"), :deal_goal ???? # add 2 columns: 'nb of deals with this goal' 'Share of deals with this goal' end end 

任何帮助将非常感激!

我想不出任何干净的方法来获得你通过ActiveRecord获得的结果,但它在SQL中非常容易。

你真正要做的就是打开deal_goal数组并根据打开的数组构建直方图。 您可以这样直接在SQL中表达它:

 with expanded_deals(id, goal) as ( select id, unnest(deal_goal) from deals ) select goal, count(*) n from expanded_deals group by goal 

如果你想包括所有四个目标,即使它们没有出现在任何一个deal_goal那么只需要在LEFT JOIN中投入即可:

 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 

SQL演示 : http : //sqlfiddle.com/#!15 / 3f0af / 20

将其中一个投入select_rows调用,您将获得您的数据:

 Deal.connection.select_rows(%q{ SQL goes here }).each do |row| goal = row.first n = row.last.to_i #.... end 

这里可能有很多你不熟悉的东西,所以我会解释一下。

首先,我使用WITH和公用表表达式(CTE)来简化SELECT。 WITH是一种标准SQLfunction ,允许您生成SQL宏或内联临时表。 在大多数情况下,您可以将CTE放在查询中,其名称为:

 with some_cte(colname1, colname2, ...) as ( some_pile_of_complexity ) select * from some_cte 

是这样的:

 select * from ( some_pile_of_complexity ) as some_cte(colname1, colname2, ...) 

CTE是将过于复杂的查询/方法重构为更小且更易于理解的部分的SQL方法。

unnest是一个数组函数,它将数组解包为单个行。 所以,如果你说unnest(ARRAY[1,2]) ,你会得到两行: 12

PostgreSQL中的VALUES或多或少地用于生成内联常量表。 你可以在任何可以使用普通表的地方使用VALUES,它不仅仅是你在INSERT中抛出的一些语法来告诉数据库要插入什么值。 这意味着你可以这样说:

 select * from (values (1), (2)) as dt 

并获取行12 。 将VALUES投入到CTE中会使事情变得美观和可读,并使其看起来像最终查询中的任何旧表。