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
のいずれにも表示されていない場合でも、4つの目標すべてを含める場合 次に、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
それらの1つをselect_rows<にスローします。 / code>
電話をかけると、データが取得されます:
Deal.connection.select_rows(%q{ SQL goes here }).each do |row|
goal = row.first
n = row.last.to_i
#....
end
ここでは、なじみのないことがたくさんあるので、少し説明します。
まず、SELECTを単純化するためにWITHとCommon Table Expressions(CTE)を使用しています。 WITHは標準のSQL機能です これにより、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])
と言うと 、2行戻ります: 1
および2
。
値 PostgreSQLでは、多かれ少なかれ、インライン定数テーブルを生成するために使用されます。 VALUESは、通常のテーブルを使用できる場所であればどこでも使用できます。挿入する値をデータベースに指示するためにINSERTをスローするのは、構文だけではありません。つまり、次のように言うことができます:
select * from (values (1), (2)) as dt
行1
を取得します および2
アウト。そのVALUESをCTEにスローすると、物事が見やすく読みやすくなり、最終的なクエリの古いテーブルのように見えます。