sql >> Databasteknik >  >> RDS >> PostgreSQL

Räkna förekomsten av värden i ett serialiserat attribut(array) i Active Admin-instrumentpanelen (Rails, Active admin 1.0, Postgresql-databas, postgres_ext gem)

Jag kan inte komma på något rent sätt att få de resultat du är ute efter genom ActiveRecord, men det är ganska enkelt i SQL.

Allt du verkligen försöker göra är att öppna deal_goal matriser och bygga ett histogram baserat på de öppnade matriserna. Du kan uttrycka det direkt i SQL på detta sätt:

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

Och om du vill inkludera alla fyra målen även om de inte visas i något av deal_goal s släng sedan bara in en LEFT JOIN för att säga så:

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

Kasta en av dessa i en select_rows ring så får du din data:

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

Det händer förmodligen mycket här som du inte är bekant med så jag ska förklara lite.

Först och främst använder jag WITH och Common Table Expressions (CTE) för att förenkla SELECT. WITH är en standard SQL-funktion som gör att du kan skapa SQL-makron eller infogade temporära tabeller av något slag. För det mesta kan du ta CTE och släppa den direkt i frågan där dess namn är:

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

är så här:

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

CTE:er är SQL-sättet att omstrukturera en alltför komplex fråga/metod till mindre och lättare att förstå delar.

unnest är en arrayfunktion som packar upp en array i individuella rader. Så om du säger unnest(ARRAY[1,2]) , får du två rader tillbaka:1 och 2 .

VÄRDEN i PostgreSQL används för att mer eller mindre generera infogade konstanttabeller. Du kan använda VALUES var som helst du kan använda en normal tabell, det är inte bara någon syntax som du lägger in en INSERT för att tala om för databasen vilka värden som ska infogas. Det betyder att du kan säga så här:

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

och hämta raderna 1 och 2 ut. Att slänga in dessa VÄRDEN i en CTE gör saker trevliga och läsbara och får det att se ut som vilken gammal tabell som helst i den slutliga frågan.




  1. GROUP_CONCAT flera fält med en annan avgränsare

  2. Oracle i C#, bindningsvariabler och frågor som ID IN (1, 2, 3)

  3. SQL-fråga för att summera data

  4. Oracle:Hur man räknar null- och icke-nullrader