MySQL Dataset mit Query erst order, dann group

  • VB.NET
  • .NET 4.0

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von Mono.

    MySQL Dataset mit Query erst order, dann group

    Hallo ich programmiere für meine Firma ein Programm in Eigenregie, das Projekte abwickelt und Baugruppen durch die verschiedenen Abteilungen schleift.

    Einige Benutzer meines Programms hatten sich gewünscht, dass man alte Stände wieder her holen kann, wenn man etwas falsch geklickt hat.
    Dies würde mit der Historie-Tabelle gehen, die bereits automatisiert seit monaten fleißig befüllt wird.

    Hierzu wird Datagridview benötigt, das anhand der Auswahl des Benutzers mit Ort und Zeit den gewünschten "Snapshot" erzeugen kann.
    Im phpMyAdmin funktioniert das Query auch einwandfrei, jedoch nicht im Visual Studio als DataSet Query...

    Der Benutzer kann dann zum Beispiel den Stand von "letzter Woche" holen und wiederherstellen.

    Anscheinend mag Visual Studio keine verschachtelten Queries, deshalb... wie könnte man das gleiche Problem im Visual Studio lösen?
    Hier wird erst ein Order By und danach ein Group by benötigt, da man ansonsten in die "falsche Richtung" grupperen würde.
    Es soll der letzte Stand zu dem Zeitpunkt x gefiltert angezeigt werden in einem Datagridview.

    SQL-Abfrage

    1. SELECT * FROM
    2. (
    3. SELECT * from elemente_history
    4. WHERE `Ort`='ABC123~22~A1A1~5001-5002~ST2' and `dt_datetime` <= '2017-06-02 00:00:00'
    5. ORDER BY dt_datetime desc
    6. )
    7. group by ID desc


    danke für die Antwort im Voraus :thumbsup:
    Hi, keine wirkliche Lösung, nur ne Idee...
    wenn ich komplizierte SQL Statements habe, dnn erstelle ich dafür eine StoredProzedur auf dem SQL-Server. Diese kann man auch aus VS heraus aufrufen. „EXEC prozedurname“
    weis aber nicht ob dies auch mit dem MySQL Server geht....
    "Hier könnte Ihre Werbung stehen..."
    Oftmals liegt das an fehlenden Argumenten im Connection String.
    Schau mal hier, was du eventuell brauchen könntest:
    dev.mysql.com/doc/connector-ne…t-connection-options.html

    Grüße
    Vainamo
    Servus,

    Visual Studio und Dataset kombiniert kommet mit geschachtelten Querires nicht klar...

    Deshalb wurde das nun ohne das DataSet gemacht und das Datagridview direkt befüllt. Hier der Quellcode falls einer dies nachmachen will:

    VB.NET-Quellcode

    1. Private Sub cmbTime_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmbTime.SelectedIndexChanged
    2. Conn.ConnectionString = My.Settings.ProjektConnectionString
    3. Conn.Open()
    4. Dim t As DataTable = mysql_query(String.Format(
    5. "SELECT * FROM ( SELECT * from elemente_history WHERE `Ort`='{0}' and `dt_datetime` <= '{1}' ORDER BY dt_datetime desc ) as meh group by ID desc ",
    6. Me.cmbComp.Text, Me.cmbTime.Text))
    7. DGV.DataSource = t
    8. Conn.Close()
    9. btnGO.Enabled = True
    10. End Sub
    11. Function mysql_query(ByVal sqlQuery As String) As DataTable
    12. Dim data As DataTable = New DataTable
    13. da = New MySqlDataAdapter(sqlQuery, Conn)
    14. cb = New MySqlCommandBuilder(da)
    15. da.Fill(data)
    16. Return data
    17. End Function


    Hinweis: wegen dem "as meh" hier könnte man alles Einfügen was man will, hatte hier gepasst.
    Wenn das nicht gemacht wird, kommt eine Fehlermeldung sowohl im VS als auch direkt im PHPMyAdmin drin mit der Meldung:
    MySQL meldet: #1248 - Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden
    Welcher Alias es ist ... ist theoretisch egal.
    Hallo, ich bin noch auf ein Problem bei dem Lösen dieses Queries gekommen, das mir zuerst nicht aufgefallen ist.

    mariadb.com/kb/en/library/why-…-a-from-subquery-ignored/

    SQL sieht den Subquery als unsortierten Query und sortiert ihn wieder selbst, welches das Order By im Subquery vernichtet.

    Ein Workaround ist auf der verlinkten Seite angegeben:

    SQL-Abfrage

    1. SELECT field1, field2 FROM (
    2. SELECT field1, field2 FROM table1
    3. ORDER BY field2
    4. LIMIT 18446744073709551615
    5. ) alias


    Meine Lösung ist also folgende:

    SQL-Abfrage

    1. SELECT * FROM
    2. (
    3. SELECT *
    4. FROM elemente_history
    5. WHERE Ort='912~0~2~2160~V01' AND dt_datetime<='2018-02-01 15:42:59'
    6. ORDER BY dt_datetime DESC
    7. LIMIT 18446744073709551615
    8. ) as elemente_history
    9. GROUP BY elemente_history.ID


    die Zeile LIMIT bewirkt, dass MySQL das Query als sortiert ansieht und den eigenen Sortieralgorithmus nicht anwendet.
    Entweder hast du dich unglücklich ausgedrückt, oder aber weder das Problem, noch den workaround zu 100% verstanden:
    Das Problem ist wie folgt:
    Der SQL Standard verbietet eigentlich ORDER BY in Subqueries, die Datenbanksysteme MySQL/MariaDB (kp. wie es mit MSSQL usw. aussieht) erlauben es aber, da in Kombination mit LIMIT in einer Subquery ein anderes Endergebnis entstehen kann. Ohne LIMIT wird es wohl einfach wegoptimiert.

    Die Lösung setzt also nicht einfach irgendwo ein magisches Flag, sondern zwingt die Engines dazu den filesort auf die Subquery auszuführen, der zuvor eben wegoptimiert wurde.
    D.H. es muss nun eine Temporäre Tabelle erstellt werden, alle Einträge sortiert, und dann das Ergebnis zurückgegeben werden.
    Post-AGB:
    §1 Mit dem Lesen dieses Posts stimmst du den AGB unverzüglich zu
    §2 Ein Widerruf muss innerhalb von 3 Sekunden nach Lesen des Hauptbestandteil des ersten jemals gelesenen Posts erfolgen
    Abs.1 Die Signatur zählt nicht zum Hauptbestandteil des Posts
    §3 Ein erfolgreicher Widerruf zwingt zu einem Besuch bei einem Hypnotiseur oder Neurochirurg, sodass der gelesene Text aus den Erinnerungen entfernt werden kann
    Abs.1 Die Kosten und Risiken sind jeweils selbst zu tragen
    Nur mal so als Tip.
    Ein GroupBy über eine ID und dann einfach alle anderen Spalten selectest kannst du dir nie sicher sein, welche Werte in den anderen Spalten stehen.
    Ein OrderBy hilft da auch nicht.
    Eigentlich korrekt wäre es mit einem Subselect auf die gruppierten Ids der Tabelle:

    SQL-Abfrage

    1. SELECT *
    2. FROM elemente_history
    3. WHERE Id IN (SELECT Id
    4. FROM elemente_history
    5. WHERE `Ort`='ABC123~22~A1A1~5001-5002~ST2' and `dt_datetime` <= '2017-06-02 00:00:00'
    6. GROUP BY Id)
    7. --ORDER BY dt_datetime desc falls erwünscht kann man das Ergebnis nun noch sortieren


    Ich wundere mich hier zwar auch wieso man überhaupt über eine ID gruppieren sollte, denn solch ein Spalte sollte eigentlich der Primärschlüssel sein und damit keinen Mehrwert durch Gruppierung bringen.
    Wenn es tatsächlich so ist das es mehrere Records mit der gleichen ID gibt dann kannst du mit einem ORDER BY vor dem Group das nicht sicher beeinflussen, in welche Richtung gruppiert wird.
    dev.mysql.com/doc/refman/5.6/en/group-by-handling.html
    MySQL unterstützt diesen NON STANDARD SQL Weg mit Spalten die nicht aggriert sind bei group by's nur aus Performancegründen wenn die Spalten alle gleich sind. Soll heißen, auch wenn es öfters klappt, kann man sich nicht darauf verlassen wirklich immer die richtigen Daten zu bekommen.

    LG
    Das ist meine Signatur und sie wird wunderbar sein!