Gruppieren anhand Werteliste

Hallo und guten Tag zusammen,

ich bin noch frischer PG-User und möchte gern “benutzerspezifisch” gruppieren.
Bsp-Tab abc unten und dann als 1. Gruppe A-C, 2. Gruppe = D-E etc., um dann jeweils die Summe der Spalte rank zu erhalten.
Bin unter GROUP BY und den hiesigen Beiträgen noch nicht fündig geworden… eine 2. Tabelle für left-joins geht für mich nicht, da only-read rights.

Mein gewünschter Output lautet
grp sum(rank)
A-C 6
D-E 9
etc.

Könnt ihr bitte helfen oder mir ein paar mögliche Befehle zuwerfen? :slight_smile:
Dank vorab & LG, Sue

CREATE TABLE abc (id INT, letter text, rank smallint);
INSERT INTO abc (id,letter,rank) VALUES (1,‘A’,1);
INSERT INTO abc (id,letter,rank) VALUES (2,‘B’,2);
INSERT INTO abc (id,letter,rank) VALUES (3,‘C’,3);
INSERT INTO abc (id,letter,rank) VALUES (4,‘D’,4);
INSERT INTO abc (id,letter,rank) VALUES (5,‘E’,5);
etc

edb=*> select * from abc;
 id | letter | rank 
----+--------+------
  1 | a      |    1
  2 | b      |    2
  3 | c      |    3
  4 | d      |    4
  5 | e      |    5
  6 | f      |    6
(6 rows)

edb=*> select ((ascii(letter)+1) / 3)::int, sum(rank) from abc group by ((ascii(letter)+1) / 3)::int;
 int4 | sum 
------+-----
   34 |  15
   33 |   6
(2 rows)

Hilft das? Aus der ersten Spalte jetzt noch irgendwie den Bereich a-c, d-f zu errechnen überlasse ich Dir zur Übung :wink:

1 Like

Wow, da geht ja hurtig hier :smiley:
Probier ich gleich aus, lieben Dank schon einmal für die Hilfe :compass:

Alternativ geht das auch mit einer CASE expression:

select case 
          when letter in ('A','B','C') then 'A-C'
          when letter in ('D','E') then 'D-E'
       end as grp ,
       sum(abc.rank)
from abc 
group by grp 
order by grp;

Das geht auch mit einem left join indem man die Gruppen als VALUES Liste zur Verfügung stellt.

select g.name, 
       sum(abc.rank)
from (
  values 
     ('Gruppe 1', array['A','B','C']), 
     ('Gruppe 2', array['D','E'])
) as g(name, letters)  
  left join abc on abc.letter = any(g.letters)
group by g.name
order by g.name;

Online Beispiel

1 Like

Super, das ist genau, was ich gesucht habe :smiley: vielen Dank, CASTORP!! :bouquet:

Danke @akretschmer für die Inspiration, den ASCII-Code für eine automatisch erzeugte Gruppierung herzunehmen, interessant! Es entstehen gleich große Klassen - ein Good-to-know für Statistiker :smiley: :wink: merke ich mir, danke ! :blossom:

1 Like

Es gibt noch eine weitere Alternative bei der man die Gruppen etwas “dynamischer” festlegen kann: über width_bucket():

select  width_bucket(letter, array['A', 'D']) as grp,
        sum(rank)
from abc
group by grp
order by grp;

Der zweite Parameter für width_bucket ist eine Liste von Werten die den Startwert jeder Gruppe definieren. Der obige Aufruf erzeugt also eine Gruppe von A-C und dann beginnend mit D (ohne Ende). Liefert halt nur 1 oder 2 zur Identifizierung der Gruppe, keine “sprechenden” Namen

1 Like

Smarte Lösung, besten Dank @castorp! Perfekt bei sortierbaren oder fortlaufenden Gruppier-Werten :smiley: