Saya tidak bisa memikirkan cara bersih apa pun untuk mendapatkan hasil yang Anda cari melalui ActiveRecord tetapi cukup mudah dalam SQL.
Yang benar-benar Anda coba lakukan adalah membuka deal_goal
array dan membangun histogram berdasarkan array yang dibuka. Anda dapat mengekspresikannya secara langsung dalam SQL dengan cara ini:
with expanded_deals(id, goal) as (
select id, unnest(deal_goal)
from deals
)
select goal, count(*) n
from expanded_deals
group by goal
Dan jika Anda ingin menyertakan keempat sasaran meskipun tidak muncul di salah satu deal_goal
s lalu masukkan LEFT JOIN untuk mengatakannya:
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
Lemparkan salah satunya ke select_rows
telepon dan Anda akan mendapatkan data Anda:
Deal.connection.select_rows(%q{ SQL goes here }).each do |row|
goal = row.first
n = row.last.to_i
#....
end
Mungkin ada banyak hal yang belum Anda ketahui, jadi saya akan menjelaskan sedikit.
Pertama-tama, saya menggunakan WITH dan Common Table Expressions (CTE) untuk menyederhanakan SELECT. DENGAN adalah fitur SQL standar yang memungkinkan Anda untuk menghasilkan makro SQL atau semacam tabel sementara. Untuk sebagian besar, Anda dapat mengambil CTE dan meletakkannya tepat di kueri di mana namanya:
with some_cte(colname1, colname2, ...) as ( some_pile_of_complexity )
select * from some_cte
seperti ini:
select * from ( some_pile_of_complexity ) as some_cte(colname1, colname2, ...)
CTE adalah cara SQL untuk memfaktorkan ulang kueri/metode yang terlalu rumit menjadi bagian yang lebih kecil dan lebih mudah dipahami.
unnest
adalah fungsi array yang membongkar array ke dalam baris individual. Jadi jika Anda mengatakan unnest(ARRAY[1,2])
, Anda mendapatkan dua baris kembali:1
dan 2
.
VALUES di PostgreSQL digunakan untuk, kurang lebih, menghasilkan tabel konstanta sebaris. Anda dapat menggunakan VALUES di mana pun Anda bisa menggunakan tabel normal, bukan hanya beberapa sintaks yang Anda masukkan ke dalam INSERT untuk memberi tahu database nilai apa yang harus dimasukkan. Artinya, Anda dapat mengatakan hal-hal seperti ini:
select * from (values (1), (2)) as dt
dan dapatkan baris 1
dan 2
keluar. Melempar VALUES itu ke dalam CTE membuat semuanya bagus dan mudah dibaca dan membuatnya terlihat seperti tabel lama di kueri terakhir.