Mir fällt kein sauberer Weg ein, um die gewünschten Ergebnisse über ActiveRecord zu erhalten, aber in SQL ist es ziemlich einfach.
Alles, was Sie wirklich versuchen, ist, deal_goal
zu öffnen Arrays und erstellen Sie ein Histogramm basierend auf den geöffneten Arrays. Sie können das direkt in SQL auf diese Weise ausdrücken:
with expanded_deals(id, goal) as (
select id, unnest(deal_goal)
from deals
)
select goal, count(*) n
from expanded_deals
group by goal
Und wenn Sie alle vier Ziele einbeziehen möchten, auch wenn sie in keinem der deal_goal
erscheinen Fügen Sie dann einfach einen LEFT JOIN hinzu, um dies zu sagen:
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-Demo :http://sqlfiddle.com/#!15/3f0af/20
Werfen Sie einen davon in einen select_rows
ruf an und du bekommst deine daten:
Deal.connection.select_rows(%q{ SQL goes here }).each do |row|
goal = row.first
n = row.last.to_i
#....
end
Hier passiert wahrscheinlich eine Menge, mit der Sie nicht vertraut sind, also erkläre ich es Ihnen ein wenig.
Zunächst verwende ich WITH und Common Table Expressions (CTE), um die SELECTs zu vereinfachen. WITH ist eine Standard-SQL-Funktion damit können Sie SQL-Makros oder eine Art eingebettete temporäre Tabellen erstellen. Zum größten Teil können Sie den CTE nehmen und ihn direkt in die Abfrage einfügen, wo sein Name lautet:
with some_cte(colname1, colname2, ...) as ( some_pile_of_complexity )
select * from some_cte
ist so:
select * from ( some_pile_of_complexity ) as some_cte(colname1, colname2, ...)
CTEs sind die SQL-Methode, um eine übermäßig komplexe Abfrage/Methode in kleinere und leichter verständliche Teile umzuwandeln.
unnest
ist eine Array-Funktion, die ein Array in einzelne Zeilen entpackt. Also, wenn Sie unnest(ARRAY[1,2])
sagen , erhalten Sie zwei Zeilen zurück:1
und 2
.
WERTE in PostgreSQL wird verwendet, um mehr oder weniger Inline-Konstantentabellen zu generieren. Sie können VALUES überall dort verwenden, wo Sie eine normale Tabelle verwenden könnten, es ist nicht nur eine Syntax, die Sie in ein INSERT werfen, um der Datenbank mitzuteilen, welche Werte eingefügt werden sollen. Das bedeutet, dass Sie Dinge wie diese sagen können:
select * from (values (1), (2)) as dt
und erhalten Sie die Zeilen 1
und 2
aus. Diese WERTE in einen CTE zu werfen, macht die Dinge schön und lesbar und lässt sie in der letzten Abfrage wie jede alte Tabelle aussehen.