Tôi không thể nghĩ ra bất kỳ cách rõ ràng nào để có được kết quả như bạn mong đợi thông qua ActiveRecord nhưng nó khá dễ dàng trong SQL.
Tất cả những gì bạn thực sự đang cố gắng làm là mở deal_goal
mảng và xây dựng biểu đồ dựa trên các mảng đã mở. Bạn có thể diễn đạt điều đó trực tiếp trong SQL theo cách này:
with expanded_deals(id, goal) as (
select id, unnest(deal_goal)
from deals
)
select goal, count(*) n
from expanded_deals
group by goal
Và nếu bạn muốn bao gồm tất cả bốn mục tiêu ngay cả khi chúng không xuất hiện trong bất kỳ deal_goal
nào sau đó chỉ cần ném một THAM GIA TRÁI để nói như vậy:
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
Bản trình diễn SQL : http://sqlfiddle.com/#!15/3f0af/20
Ném một trong những thứ đó vào select_rows
gọi và bạn sẽ nhận được dữ liệu của mình:
Deal.connection.select_rows(%q{ SQL goes here }).each do |row|
goal = row.first
n = row.last.to_i
#....
end
Có thể có nhiều điều đang xảy ra ở đây mà bạn không quen nên tôi sẽ giải thích một chút.
Trước hết, tôi đang sử dụng WITH và Common Table Expressions (CTE) để đơn giản hóa các SELECT. WITH là một tính năng SQL tiêu chuẩn điều đó cho phép bạn tạo macro SQL hoặc các bảng tạm thời được sắp xếp nội tuyến. Đối với hầu hết các phần, bạn có thể lấy CTE và thả nó ngay trong truy vấn có tên của nó là:
with some_cte(colname1, colname2, ...) as ( some_pile_of_complexity )
select * from some_cte
là như thế này:
select * from ( some_pile_of_complexity ) as some_cte(colname1, colname2, ...)
CTE là cách SQL để cấu trúc lại một truy vấn / phương thức quá phức tạp thành các phần nhỏ hơn và dễ hiểu hơn.
unnest
là một hàm mảng giải nén một mảng thành các hàng riêng lẻ. Vì vậy, nếu bạn nói unnest(ARRAY[1,2])
, bạn nhận lại hai hàng:1
và 2
.
GIÁ TRỊ trong PostgreSQL, ít nhiều được sử dụng để tạo các bảng hằng số nội tuyến. Bạn có thể sử dụng VALUES ở bất cứ đâu mà bạn có thể sử dụng một bảng thông thường, nó không chỉ là một số cú pháp mà bạn đưa vào INSERT để cho cơ sở dữ liệu biết những giá trị nào cần chèn. Điều đó có nghĩa là bạn có thể nói những điều như sau:
select * from (values (1), (2)) as dt
và lấy các hàng 1
và 2
ngoài. Ném các GIÁ TRỊ đó vào CTE làm cho mọi thứ trở nên đẹp đẽ và dễ đọc và làm cho nó trông giống như bất kỳ bảng cũ nào trong truy vấn cuối cùng.