nomox: Errechne Summe aus speziellen Einträgen

Moin,

ich suche nach einer Möglichkeit die Summe von bestimmten Elementen zu errechnen.

Die Tabelle tab mit

pnr | anr | euro
1 | 1.1.1 | 2
1 | 1.1.2 | 4
1 | 1.1.3 | 3 [x]
1 | 1.2.1 | 5
1 | 1.2.2 | 1 [x]
1 | 1.3.1 | 3 [x]
1 | 1.4.1 | 5
1 | 1.4.2 | 8
1 | 1.4.3 | 2 [x]
2 | 1.1.1 | 2 [x]
2 | 1.2.1 | 4
2 | 1.2.2 | 4
2 | 1.2.3 | 5 [x]
2 | 1.3.1 | 1 [x]

Filterkriterium ist die Spalte anr. Die hat den Aufbau A.B.C wowei A immer 1 ist (ist halt so), B die Stelle und C die Stellenbesetzung.

Summiert werden sollen alle euro der höchsten Stellenbesetzungen - also je pnr die Zeilen mit [x]

i.e.
SELECT SUM(euro)
FROM tab
WHERE pnr = 1
AND "Filter"

Summe gleich 9 und für pnr = 2 Summe gleich 8

Der Filter müßte von jeder Stelle (B) die höchste Stellenbesetzung (C) finden und summieren.

Hat jemand eine Idee?!?

Da die Sache als Subselect ausgeführt werden soll, ist eine Suche per PHP o.ä. möglichst zu umgehen...

Mit Dank!!

  1. Hello,

    Filterkriterium ist die Spalte anr. Die hat den Aufbau A.B.C wowei A immer 1 ist (ist halt so), B die Stelle und C die Stellenbesetzung.

    das bricht dir das Genick - du hast quasi nicht-atomare Daten vorliegen, auf denen du jetzt eine Auswertung machen willst.
    Ja, es geht trotzdem, aber nur mit Aufwand. Du musst im Prinzip in einem SUBSELECT mit Stringfunktionen arbeiten, sprich eine Art SPLIT auf den letzten "." durchführen, Gruppieren nach den Stellen vorher, schematisch
    SELECT stellen_vor_dem_punkt, MAX(stelle_nach_dem_punkt)
    FROM ...
    GROUP BY stellen_vor_dem_punkt

    Das Ergebnis wiederum kannst du als korrelierte Unterabfrage oder Teil der FROM-Klausel einsetzen um nur die Datensätze zu erhalten, die für dich relevant sind.

    MfG
    Rouven

    --
    -------------------
    sh:| fo:} ch:? rl:( br:& n4:{ ie:| mo:} va:) js:| de:] zu:| fl:( ss:) ls:& (SelfCode)
    There's no such thing as a free lunch  --  Milton Friedman
    1. Hi

      Rouven

      Folgendes funktioniert schonmal:

      SELECT
      SUBSTRING_INDEX( anr, '.', 2 ) AS 'AB',
      CONCAT(SUBSTRING_INDEX( anr, '.', 2 ),'.',MAX(SUBSTRING_INDEX( anr, '.', -1 ))) AS 'ABC'

      FROM tab1

      WHERE pnr =1

      GROUP BY AB

      wenn ich jetzt ein Subselect vor FROM einsetze und anr=ABC reinsetze, streikt MySQL, dass Group-By Parameter nicht verwendet werden dürfen..??

      Wie meinst Du das mit "Teil der FROM-Klausel"?

      Dank vorab!

      1. Hello,

        Wie meinst Du das mit "Teil der FROM-Klausel"?

        du musst zunächst das SELECT ausführen, das dir den korrekten anr Wert gibt. Das ist genau das mit dem GROUP BY und den Substrings.
        Mit dieser anr kannst du dann erneut suchen gehen, z.B.

        SELECT ...  
        FROM ...  
        WHERE anr IN (<hier das unterselect>)
        

        Alternativ lässt sich das ganze vmtl. auch über einen JOIN lösen, wobei cih jetzt vom Rest der Abfrage abhängig machen würde, welche Version zugänglicher ist.

        MfG
        Rouven

        --
        -------------------
        sh:| fo:} ch:? rl:( br:& n4:{ ie:| mo:} va:) js:| de:] zu:| fl:( ss:) ls:& (SelfCode)
        Don't lick your wounds: celebrate them. The scars you bear are the signs of a competitor.  --  character Richard Webber on Grey's Anatomy: 'Where the wild things are'
      2. Hi

        Rouven

        Folgendes funktioniert schonmal:

        SELECT
        SUBSTRING_INDEX( anr, '.', 2 ) AS 'AB',
        CONCAT(SUBSTRING_INDEX( anr, '.', 2 ),'.',MAX(SUBSTRING_INDEX( anr, '.', -1 ))) AS 'ABC'.....

        wäre nicht etwas in der Art einfacher: "SELECT substr(a,1,1)*100+substr(a,3,1)*10+substr(a,5,1) AS t FROM test ORDER BY t" um anschließend zu Joinen oder Subselecten?
        Für meinen Teil würde ich allerdings das Tabellenlayout überdenken und entsprechend der Anforderungen ändern. Machbarkeitsstudien sollten nicht für die Programmierung von Software herhalten! ;)

      3. Hallo,

        Folgendes funktioniert schonmal:

        SELECT
        SUBSTRING_INDEX( anr, '.', 2 ) AS 'AB',
        CONCAT(SUBSTRING_INDEX( anr, '.', 2 ),'.',MAX(SUBSTRING_INDEX( anr, '.', -1 ))) AS 'ABC'

        hast Du dies auch schon mit Werten wie 9 und 11 in C bei gleichem B getestet?

        Freundliche Grüße

        Vinzenz

  2. yo,

    wichtig ist das dbms und die version, die du verwendest. ich sehe hier weniger GROUP BY zum einsatz kommen, sondern korrelierte unterabfragen in verbindung mit einer speziellen funktion. diese funktion gibt dir die stelle eines vorkommenden zeichens zurück (in deinem falle den Punkt).

    in oracle heisst diese funktion instr() und hat eine besonderheit, du kannst nicht nur das zeichen angeben, das gesucht werden soll, sondern auch bestimmten, ob es das erste vorkommen des zeichen suchen soll, das zweite, dritte usw.

    dieses hat einige vorteile, so kannst du deinen string in der spalte anr aufsplitten. ich habe dies schon einige mal bei csv dateien gemacht, die als string eingelesen wurden und dann anhanf der ";" zeichen aufgetrennt werden.

    es gibt auch einen workaround, falls du bei mysql instr() nicht festlegen kannst, ab welches zeichen gesucht werden soll. oder aber du schreibst dir solch eine funktion selber und setzt sie dann ein.

    Ilja

    1. yo,

      ich habe heute früh noch mal in die doku von mysql geschaut. bei INSTR() kann man leider nicht wie bei oracle das x-te vorkommen eines zeichens suchen lassen. aber es gibt eine ganz ähnliche funktion names SUBSTRING_INDEX(), die du benutzen kannst.

      wie gesagt, der erste ansatz ist ein wenig schwierig, aber falls du hilfe dabei benötigtst, sag bescheid. man könnte sich auch eine eigene funktion basteln, die dir einen teilstring zwischen zwei wählbaren zeichen zurück gibt. wäre auch was feines.

      Ilja