PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Conta l'occorrenza di valori in un attributo serializzato (array) nella dashboard di Active Admin (Rails, Active admin 1.0, database Postgresql, postgres_ext gem)

Non riesco a pensare a un modo pulito per ottenere i risultati che cerchi tramite ActiveRecord, ma è abbastanza semplice in SQL.

Tutto quello che stai veramente cercando di fare è aprire il deal_goal array e costruire un istogramma basato sugli array aperti. Puoi esprimerlo direttamente in SQL in questo modo:

with expanded_deals(id, goal) as (
    select id, unnest(deal_goal)
    from deals
)
select goal, count(*) n
from expanded_deals
group by goal

E se vuoi includere tutti e quattro gli obiettivi anche se non compaiono in nessuno dei deal_goal s quindi inserisci un LEFT JOIN per dirlo:

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

Dimostrazione SQL :http://sqlfiddle.com/#!15/3f0af/20

Getta uno di questi in un select_rows chiama e avrai i tuoi dati:

Deal.connection.select_rows(%q{ SQL goes here }).each do |row|
  goal = row.first
  n    = row.last.to_i
  #....
end

Probabilmente stanno succedendo molte cose che non conosci, quindi ti spiego un po'.

Prima di tutto, sto usando WITH e Common Table Expressions (CTE) per semplificare i SELECT. CON è una funzionalità SQL standard che ti consente di produrre macro SQL o tabelle temporanee inline di un tipo. Per la maggior parte, puoi prendere il CTE e rilasciarlo direttamente nella query in cui il suo nome è:

with some_cte(colname1, colname2, ...) as ( some_pile_of_complexity )
select * from some_cte

è così:

select * from ( some_pile_of_complexity ) as some_cte(colname1, colname2, ...)

I CTE sono il modo SQL di refactoring di una query/metodo eccessivamente complesso in parti più piccole e di più facile comprensione.

unnest è una funzione array che decomprime un array in singole righe. Quindi, se dici unnest(ARRAY[1,2]) , ottieni due righe indietro:1 e 2 .

VALORI in PostgreSQL è usato, più o meno, per generare tabelle costanti inline. Puoi usare VALUES ovunque tu possa usare una tabella normale, non è solo una sintassi che inserisci in un INSERT per dire al database quali valori inserire. Ciò significa che puoi dire cose come questa:

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

e ottieni le righe 1 e 2 fuori. Lanciare quei VALUES in un CTE rende le cose piacevoli e leggibili e lo fa sembrare una qualsiasi vecchia tabella nella query finale.