【问题标题】:Count occurrence of values in a serialized attribute(array) in Active Admin dashboard (Rails, Active admin 1.0, Postgresql database, postgres_ext gem)在 Active Admin 仪表板(Rails、Active admin 1.0、Postgresql 数据库、postgres_ext gem)中计算序列化属性(数组)中值的出现次数
【发布时间】:2013-12-21 14:46:03
【问题描述】:

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

我的应用是一款 Daily Deal 应用,旨在了解更多 Ruby on Rails。

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

这是取自 schema.db 的 deal_goal:

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

所以一笔交易 A 可以有 deal= 目标 =[流量,资格],而另一笔交易可以有 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

任何帮助将不胜感激!

【问题讨论】:

    标签: ruby-on-rails arrays ruby-on-rails-3 postgresql activeadmin


    【解决方案1】:

    我想不出任何干净的方法来通过 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_goals 中,那么只需加入 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 is a standard SQL feature 允许您生成 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

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

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

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

    【讨论】:

    • 非常感谢。我认为您在 sql 命令中执行此操作是正确的,我尝试在纯 ruby​​ 中执行此操作,但这不是要走的路。您的建议确实有很多内容,感谢您的详细解释。今晚我会在我的应用程序上试一试,然后告诉你它是如何工作的。非常感谢您的帮助!!!
    • 谢谢。我现在确实设法在数组数组中获取我需要的所有数据,但我不能使用它们/将它们放在标准活动管理员的列中。我不知道您是否熟悉活动管理员,但我选择将此问题放在另一个问题中:stackoverflow.com/questions/20730588/…
    • 你知道如何在活动管理员的 table_for 中使用这个数组吗?
    • 对不起,我对 ActiveAdmin 一无所知,因为我不使用它。如果它的态度如此之大以至于无法显示简单的原始数据表,我会感到非常惊讶。然而,Rails 世界有一种可悲的趋势,就是用意见和态度来代替普通的好感。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 2013-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多