PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Compter l'occurrence des valeurs dans un attribut sérialisé (tableau) dans le tableau de bord Active Admin (Rails, Active admin 1.0, base de données Postgresql, gemme postgres_ext)

Je ne vois aucun moyen propre d'obtenir les résultats que vous recherchez via ActiveRecord, mais c'est assez facile en SQL.

Tout ce que vous essayez vraiment de faire est d'ouvrir le deal_goal tableaux et construire un histogramme basé sur les tableaux ouverts. Vous pouvez exprimer cela directement en SQL de cette façon :

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

Et si vous souhaitez inclure les quatre objectifs même s'ils n'apparaissent dans aucun des deal_goal s puis ajoutez simplement un LEFT JOIN pour le dire :

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

Démo SQL :http://sqlfiddle.com/#!15/3f0af/20

Jetez-en un dans un select_rows appelez et vous obtiendrez vos données :

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

Il se passe probablement beaucoup de choses ici que vous ne connaissez pas, alors je vais vous expliquer un peu.

Tout d'abord, j'utilise WITH et Common Table Expressions (CTE) pour simplifier les SELECT. WITH est une fonctionnalité SQL standard qui vous permet de produire des macros SQL ou des tables temporaires en ligne d'un tri. Pour la plupart, vous pouvez prendre le CTE et le déposer directement dans la requête où se trouve son nom :

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

est comme ça :

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

Les CTE sont le moyen SQL de refactoriser une requête/méthode trop complexe en éléments plus petits et plus faciles à comprendre.

unnest est une fonction de tableau qui décompresse un tableau en lignes individuelles. Donc, si vous dites unnest(ARRAY[1,2]) , vous récupérez deux lignes :1 et 2 .

VALEURS dans PostgreSQL est utilisé pour, plus ou moins, générer des tables de constantes en ligne. Vous pouvez utiliser VALUES partout où vous pourriez utiliser une table normale, ce n'est pas seulement une syntaxe que vous lancez dans un INSERT pour dire à la base de données quelles valeurs insérer. Cela signifie que vous pouvez dire des choses comme ceci :

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

et obtenir les lignes 1 et 2 dehors. Jeter ces VALEURS dans un CTE rend les choses agréables et lisibles et les fait ressembler à n'importe quelle ancienne table dans la requête finale.