Ankündigung

Einklappen
Keine Ankündigung bisher.

MySQL: Gruppieren und Gruppenelemente mit in der Zeile ausgeben

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • MySQL: Gruppieren und Gruppenelemente mit in der Zeile ausgeben

    Hi,
    folgendes Problem, welches ich bereits mit Hilfe von PHP gelöst habe und auch zufriedenstellend arbeitet.
    Ich habe eine Tabelle wie folgt
    Code:
    "id"    "datumzeit"            "messwert"
    "2"    "2017-08-28 15:20:01"    "24,56"
    "3"    "2017-08-28 15:20:01"    "0"
    "4"    "2017-08-28 15:20:01"    "0"
    "2"    "2017-08-28 15:30:01"    "24,6"
    "3"    "2017-08-28 15:30:01"    "0"
    "4"    "2017-08-28 15:30:01"    "0,2"
    und möchte nun für eine Liste von mehreren id's (z.B. 2,4) nach datumzeit gruppiert letztendlich ein Array ähnlich der Form
    Code:
    [
      ["datumzeit" => "2017-08-28 15:20:01", "2" => "24.56", "4" => "0"]
      ["datumzeit" => "2017-08-28 15:30:01", "2" => "24.6", "4" => "0.2"]
    ]
    erhalten.
    Gibt es hierfür einen Ansatz für eine reine SQL-Lösung den ich nicht sehe?



  • #2
    Hi,

    Ich habe gerade keine MySQL-Tabelle zum Testen griffbereit, aber schnell mal in T-SQL gebaut ( sollte unter MySQL eigentlich genau so gehen ):
    Code:
    select datumzeit, id, sum(messwert) messwerte
    from tabelle where id in ( 2,4 )
    group by datumzeit, id order by datumzeit
    für MySQL müsstest Du das WHERE ... IN aufbröseln zu OR oder evtl. mit FIELD_IN_SET() was machen.
    Damit hast Du zumindest schon mal ein geordnetes Ergebnis:
    Code:
     
    2017-08-28 15:20:00.000 2 24,56
    2017-08-28 15:20:00.000 4 0,00
    2017-08-28 15:30:00.000 2 24,60
    2017-08-28 15:30:00.000 4 0,20
    Wie man den letzten Step nun noch mit MySQL hinbekommt, weiß ich leider grad auch nicht.
    Competence-Center -> Enjoy the Informatrix
    PHProcks!Einsteiger freundliche TutorialsPreComposed Packages

    Kommentar


    • #3
      Hilft dir dieser Link mit Pivotanwendung weiter?

      Kommentar


      • #4
        Ja, Pivot war das fehlende Stichwort. Für eine fixe Liste mit id's kann dies mit MySQL z.B. so
        Code:
        SELECT 
         datumzeit , 
         AVG(IF(id=2,messwert,null)) as mw2,
         AVG(IF(id=4,messwert,null)) as mw4
         FROM messdat
        WHERE id IN (2,4)
        GROUP BY datumzeit
        HAVING COUNT(id) >= 2
        realisiert werden. Für eine dynamische Liste von id's muss obiges SQL generiert werden.

        Kommentar


        • #5
          Bist Du sicher, dass Du "having count >= 2 " brauchst?, was ist mit 1? Würde mal nur ein Wert eingetragen sein, fiele er raus.
          Dein "Pivot" würde ja 2 Spalten gemäß der beiden AVG im select Teil liefern, das sieht nicht so sehr nach dem aus, was Du im ersten Post geschrieben hast.

          Kommentar


          • #6
            Ja, das ist so gewollt. Datensätze, für die nicht alle id's der Gruppe verfügbar sind, sollen nicht ausgewählt werden. Es ist durch die Erfassung sichergestellt, das die Elemente einer Gruppe auch den gleichen Zeitstempel haben und auch Einträge existieren. Ich sehe jetzt auch nicht den Widerspruch zum ersten Post. Es können in der Tabelle messdat noch weitere Gruppen von id's ihre Werte ablegen. Die Datensätze mit der id=3 im Beispiel sollen nur andeuten, das noch weitere vorhanden sein können. Im obigen Beispiel liegen die Werte mit der id=3 im gleichen Zeitraster, das muss aber nicht so sein.

            Kommentar


            • #7
              Mal ein "kleiner" Zwischenbericht..
              Habe jetzt eine Methode erstellt, welche mir die SQL-Anweisung zusammenbaut. Ausgehend von diesen Daten
              Code:
              CREATE TEMPORARY TABLE t (
                name   varchar(60)
              , fach    varchar(60)
              , zensur        integer
              );
              
              INSERT INTO t VALUES
                ('Alex','Mathematik',2),
                ('Alex','Musik',3),
                ('Alex','Sport',1),
                ('Fritz','Mathematik',1),
                ('Fritz','Musik',1),
                ('Fritz','Sport',3);
              erzeuge ich mit
              PHP-Code:
              $fach = array("Mathematik","Musik","Sport");
              $sql $db->buildPivotSelect('t','name','fach',$fach,'zensur'); 
              nun folgendes SQL für MySQL
              Code:
              SELECT
                `name`  ,
                MAX(CASE WHEN  `fach` ='Mathematik' THEN  `zensur`  END) AS  `zensur_Mathematik` ,
                MAX(CASE WHEN  `fach` ='Musik' THEN  `zensur`  END) AS  `zensur_Musik` ,
                MAX(CASE WHEN  `fach` ='Sport' THEN  `zensur`  END) AS  `zensur_Sport`
              FROM  `t`
              WHERE  `fach`  IN('Mathematik','Musik','Sport')
              GROUP BY  `name`
              Gegenüber Post #4 sind hier 2 Änderungen eingeflossen:
              1. Das fixe HAVING ist erstmal nicht mehr vorhanden, kann aber per Option aktiviert werden.
              2. Im SQL wurde das IF wurde durch ein CASE-Konstrukt ersetzt. Das u.A. den Vorteil, das dies vom Grundsatz so auch mit SQLite funktioniert. Könnte auch unter MS_SQL und PostgreSQL funktionieren, hab jedoch aktuell keine DB zum testen parat.
              Mit den obigen Testdaten erhalte ich mit einer DB-Abfrage dann ein Ergebnis wie
              Code:
              name | zensur_Mathematik | zensur_Musik | zensur_Sport
              -----+-------------------+--------------+-------------
              Alex | 2                 | 3            | 1
              Fritz| 1                 | 1            | 3
              Edit:
              Läuft wohl so auch unter MS-SQL und PostgreSQL, wenn man dem SQL-Fiddle glauben kann (sqlfiddle). Wobei PostgreSQL ja crosstab kennt, da blicke ich nur nicht durch.

              Kommentar

              Lädt...
              X