Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   SQLite + DBGrid + Sortieren über Spalten Click (https://www.delphipraxis.net/178598-sqlite-dbgrid-sortieren-ueber-spalten-click.html)

Andidreas 16. Jan 2014 16:15

Datenbank: SQLite • Version: ? • Zugriff über: UniDac

SQLite + DBGrid + Sortieren über Spalten Click
 
Hallo zusammen,

ich verwende in meinem Programm eine SQLite Datenbank.
Die User möchten nun das Sie über den Klick auf den Titel einer Spalte die Datenmenge nach dieser Spalte Sortieren, so wie es halt auch fast jedes Programm macht.

Ich hab das bisher noch nie umsetzen müssen und hab bisl im Internet darüber gesucht.

Hab ich das richtig interpretiert das man die Datenmenge im DBGrid nicht sortieren kann, sondern das man den SQL Befehl erneut mit der Order By Klausel absetzen muss?

Mein Lösungsansatz (der auch funktioniert) sieht bisher wie folgt aus:

Delphi-Quellcode:
  //Get Sort Column Number and Name
  If Column.Index = giSortColumn Then
  Begin
    If gsSortOrder = 'ASC' Then gsSortOrder := 'DESC' Else gsSortOrder := 'ASC';
  End Else
  Begin
    gsSortOrder := 'ASC';
  End;

  giSortColumn := Column.Index;
  sFieldName := Column.FieldName;


  //Sort
  Try
    With (sqlitefile_query1) Do
    Begin
      Active := False;
      datsrc_test.DataSet := Nil;
      SQL.Clear;
      SQL.Add('Select * From DATCOM');
      SQL.Add('Order By ' + sFieldName + ' ' + gsSortOrder);
      datsrc_test.DataSet := sqlitefile_query1;
      Active := True;
    End;
  Except
    On E:Exception Do
    Begin
      MessageDlg(E.Message, mtError, [mbOK], 0);
      Exit;
    End;
  End;

  //Show Sort Column
  dbgrid_test.Columns[giSortColumn].Title.Font.Style := dbgrid_test.Columns[giSortColumn].Title.Font.Style + [fsBold];
giSortColumn und gsSortOrder sind Globale Variablen in denen ich mir den letzten Sortier Stand merke.

sx2008 16. Jan 2014 18:12

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Zitat:

Zitat von Andidreas (Beitrag 1244004)
Hab ich das richtig interpretiert das man die Datenmenge im DBGrid nicht sortieren kann, sondern das man den SQL Befehl erneut mit der Order By Klausel absetzen muss?

Richtig.
Es sei denn du verwendest ein Grid, dass die Datenmenge intern zwischenspeichert und daher auch sortieren kann.
wie z.B.
https://www.devexpress.com/products/vcl/exquantumgrid/

Perlsau 17. Jan 2014 01:39

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Zitat:

Zitat von Andidreas (Beitrag 1244004)
Hab ich das richtig interpretiert das man die Datenmenge im DBGrid nicht sortieren kann, sondern das man den SQL Befehl erneut mit der Order By Klausel absetzen muss?

Nicht unbedingt, wenn man wie du UniDac einsetzt. Denn in den zugehörigen Dataset- bwz. Query-Komponenten gibt es das Property IndexFieldNames, dem du einfach den Feldnamen, nach dem sortiert werden soll, als String übergibst. Du kannst auch nach mehreren Feldern sortieren, z.B. erst nach Nachnamen und dann nach Vornamen:

Delphi-Quellcode:
MyQuery.IndexFieldNames := 'Nachname ASC CIS; Vorname DESC';


Da UniDac und IbDac aus derselben Schmiede stammen, gehe ich mal davon aus, daß das, was in meiner IbDac-Hilfe steht, auch für UniDac gilt:

Use the IndexFieldNames property to get or set the list of fields on which the recordset is sorted. Specify the name of each column in IndexFieldNames to use as an index for a table. Ordering of column names is significant. Separate names with semicolon. The specified columns don't need to be indexed. Set IndexFieldNames to an empty string to reset the recordset to the sort order originally used when the recordset's data was first retrieved.
Each field may optionally be followed by the keyword ASC / DESC or CIS / CS / BIN.
Use ASC, DESC keywords to specify a sort direction for the field. If one of these keywords is not used, the default sort direction for the field is ascending.
Use CIS, CS or BIN keywords to specify a sort type for string fields:
CIS - compare without case sensitivity;
CS - compare with case sensitivity;
BIN - compare by character ordinal values (this comparison is also case sensitive).
If a dataset uses a TCustomDAConnection component, the default value of sort type depends on the TCustomDAConnection.Options option of the connection. If a dataset does not use a connection (TVirtualTable dataset), the default is CS.
Read IndexFieldNames to determine the field (or fields) on which the recordset is sorted.
Ordering is processed locally.
Note: You cannot process ordering by BLOB fields.


Wenn man eine Komponente erwirbt, ist es meist nicht verkehrt, sich die Dokumentation dazu anzuschauen, bevor man sie einsetzt.

Furtbichler 17. Jan 2014 06:36

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Bei ADO geht das auch (in-Memory sorting),indem Du die Eigenschaft 'IndexFieldNames' belegst (Feldnamen durch Semikolon getrennt).

Allgemein gesehen ist es ziemlicher Blödsinn, die Daten vom Server sortieren zu lassen. Sortieren ist doch ein wenig Ressourcenfressend und so ein DB-Server ist dafür eigentlich zu schade. Und wenn Du nun mal nicht eine SQLite-DB hast, sondern später mal eine richtige DB, bei der mehrere Leute dran sitzen und die klicken munter auf die Sortierspalten, dann ist der Server so mit Sortieren beschäftigt, das er andere Sachen nicht mehr zeitnah hinbekommt.
Lieber heute richtig anfangen, als sich morgen falsche Sachen angewöhnt haben. Nur in sehr seltenen Fällen, nämlich wenn die anzuzeigende Tabelle soviele Daten enthält, das Du die gar nicht alle in den lokalen Speicher bekommst, sollte man das dem Server überlassen. Dann aber auch nur mit Index auf jeder Spalte, was auch wieder behämmtert ist (Stichwort: Index-Shotgun).

Richtig ist, ein Grid oder ein in-Memory Dataset zu verwenden, das das Sortieren eben lokal erledigt. Warum auch nicht, denn die Daten sind doch eh schon da. Nur das dämliche TDBGrid kann das eben nicht.

Wenn deine TDataset-Komponente das nicht kann, dann kopiere die Daten in ein TClientDataset, das kann -glaube ich zumindest- sortieren.

Edit: Hab gerade 'UniDac' gelesen.. Na dann gehts ja.

arnof 17. Jan 2014 09:56

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
ADO : xxx.Sort='FELDDNAME';

TClientDataSet: xxx.IndexName:='Feldname';

Dac: keine Ahnung, das will noch entdeckt werden!

Andidreas 17. Jan 2014 10:17

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Vielen Dank für die Tipps.

Das mit den IndexFieldNames habe ich ausprobiert und funktioniert einwandfrei!

Ich hab nur noch eine Verständnisfrage...
Wenn ich im SQL eine Ordre By Klausel hab, werden meine Daten sobald ich sie im DBGrid hab ja erst mal nach diesen Kriterien sortiert.

Wie verhält sich das wenn ich dann über IndexFieldNames sortiere?
Die Order By Klausel wird dann ja ausser Kraft gesetzt oder nicht?

DeddyH 17. Jan 2014 10:20

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Vereinfacht ausgedrückt: das ORDER BY legt die Reihenfolge fest, in der der Server die Datensätze zum Client schickt. Wenn Letzterer sie aber einmal lokal zwischengespeichert hat, kann er sie wieder umsortieren, wie er lustig ist.

arnof 17. Jan 2014 10:51

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Order By , hier muss eine SQL Abfrage Neu gemacht werden (Daten kommen sortiert vom Server)

IndexName, das Betrift die Daten, die sich nach dem laden im ClientDataSet befinden, die werden in der Komponente sortiert und Betrift nur die Daten, die dort drin sind unabhängig vom SQL Server!

Andidreas 17. Jan 2014 10:58

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Ok, dann wäre es so wie ich es haben möchte...

Noch ne andere Frage...
Meine Tests habe ich in einem Testprogramm gemacht wo ich ein DBGrid verwendet hab wo an den Einstellungen nichts verändert wurde...
Jetzt versuch ich das ganze in mein bestehendes Programm einzubauen und auf einmal kommt mein Programm nicht mehr ins "OnColumnTitleClick" Ereignis... :shock:

Gibt es Einstellungen die das verhinden können?

Jumpy 17. Jan 2014 11:00

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Ich vermute mal das durch das rüberkopieren von Codezeilen ist das Event des Grids noch nicht mit dem Code verknüpft oder die Komponenten heißen anders o.ä.

Andidreas 17. Jan 2014 11:06

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Nee, einfacher...
Ich hatte in den Options dgTitleClick deaktiviert :oops:

Andidreas 17. Jan 2014 11:38

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Muss man beim Sortieren von Zahlenwerten noch etwas berücksichtigen?

Die werden bei mir gerade z.B. wie folgt sortiert:

100
11
12
200

Ich hab diese Werte leider als String Werte in der SQLite, Caste Sie aber zu Integers
Code:
CAST(SUM(Feld1) as Integer)
Jetzt weiß ich aber nicht woher das Problem kommt... Ob es an meinem Datentyp in der DB liegt und das Casten nichts bringt oder ob es an der Sortierung an sich liegt...

Hab schon CIS und BIN ausprobiert...

blondervolker 17. Jan 2014 16:01

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Datamodule1.KUTable.Sort := '[DEIN_VORNAME]';//1.Spalte
Datamodule1.KUTable.Sort := '[DEIN_NAME]';//1.Spalte

usw.

Furtbichler 17. Jan 2014 19:09

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Zitat:

Zitat von arnof (Beitrag 1244080)
ADO : xxx.Sort='FELDDNAME';

Echt? :gruebel: Stimmt. :thumb:

blondervolker 18. Jan 2014 12:04

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
:cyclops:

Andidreas 20. Jan 2014 13:20

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Zitat:

Zitat von blondervolker (Beitrag 1244154)
Datamodule1.KUTable.Sort := '[DEIN_VORNAME]';//1.Spalte
Datamodule1.KUTable.Sort := '[DEIN_NAME]';//1.Spalte

usw.

Wie darf ich diesen Kommentar interpretieren? Zu meinem Zahlen Problem passt der ja nicht ganz?!

p80286 20. Jan 2014 13:50

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Zitat:

Zitat von Andidreas (Beitrag 1244099)
Ich hab diese Werte leider als String Werte in der SQLite, Caste Sie aber zu Integers
Code:
CAST(SUM(Feld1) as Integer)

Ah ha, wahrscheinlich fehlt mir die notwendige Phantasie. Wenn dies numerische Werte sein sollen, warum sind diese dann nicht numerisch in der DB abgelegt?
Wenn Du numerische Werte in einem (..)Grid anzeigst, sind sie nicht mehr numerisch.
Wo zum .. sortierst Du und wo führst Du den Cast aus?

(und alle die sagen, das ein Grid nur für die Anzeige ist, grinsen jetzt)

Gruß
K-H

baumina 20. Jan 2014 13:56

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Dass ein SUM() überhaupt auf Strings geht, ist mir neu.

Andidreas 20. Jan 2014 14:18

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Zitat:

Zitat von baumina (Beitrag 1244549)
Dass ein SUM() überhaupt auf Strings geht, ist mir neu.

Naja das is ja DB abhängig und die SQLite kanns wohl...

Zitat:

Zitat von p80286 (Beitrag 1244547)
Zitat:

Zitat von Andidreas (Beitrag 1244099)
Ich hab diese Werte leider als String Werte in der SQLite, Caste Sie aber zu Integers
Code:
CAST(SUM(Feld1) as Integer)

Ah ha, wahrscheinlich fehlt mir die notwendige Phantasie. Wenn dies numerische Werte sein sollen, warum sind diese dann nicht numerisch in der DB abgelegt?
Wenn Du numerische Werte in einem (..)Grid anzeigst, sind sie nicht mehr numerisch.
Wo zum .. sortierst Du und wo führst Du den Cast aus?

(und alle die sagen, das ein Grid nur für die Anzeige ist, grinsen jetzt)

Gruß
K-H

Ich hatte sie nicht numerisch in der DB, da mein Programm eine Text Datei in die Tabelle importiert die ich sortieren möchte. Ich muss zugeben das es ich mir beim import einfach machen wollte und alle Werte als Strings importiert habe.
Mittlerweile hab ichs auf den Feldtyp "int" umgestellt.

Betrachte ich meine SQLite Tabelle mit dem SQLiteManager Add-On im Firefox werden die Daten durch ein "Order By" richtig sortiert.

Sortiere ich im Programm über die UniDac Komponente mit einem "Order By" habe ich wieder das beschriebene Problem das er nicht richtig sortiert.
Dasselbe habe ich wenn ich nach einem Klick auf die Spalten Überschrift mit "IndexFieldName" sortiere.

Hatte jemand schon mal solche Probleme?

Andidreas 20. Jan 2014 14:32

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Liegt das evtl. an der SUM() Funktion???

Wenn ich die Daten ohne Group By und und SUM() Funktion abhole und über die IndesFieldName Funktion der TUniQuery sortiere, dann klappt alles mit dem sortieren.

Wenn ich aber in meinem SQL Befehl einen SUM() habe mit Group By und danach sortiere dann bekomme ich wieder die falsche Sortierung...

Hier mal ein Code Beispiel wie ich es meine:

SQL
Code:
Select Commissions, Sum(Menge) as "Kommissions Menge" From Tabelle1
Group By Commissions
Delphi Source für die Sortierung
Delphi-Quellcode:
  SQLiteFile_DisplayCommissions.IndexFieldNames := '"' + sFieldName + '" ' + gsSortOrder + ';';


sFieldName würde z.B. die DBGrid Spaltenüberschrift "Kommissions Menge" beinhalten.
Der SQL beinhaltet einen Group By da die Kommission aus mehreren Positionen besteht und in einer Info Ansicht die Gesamtmenge angezeigt werden soll...

baumina 20. Jan 2014 14:36

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Feldname mit Leerzeichen, geht das tatsächlich?

DeddyH 20. Jan 2014 14:38

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Entsprechend gequotet geht das AFAIK so ziemlich mit jedem DBMS.

Andidreas 20. Jan 2014 14:40

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Zitat:

Zitat von baumina (Beitrag 1244556)
Feldname mit Leerzeichen, geht das tatsächlich?

Ja das geht solang ich den Feldnamen in Anführungszeichen (") setze so wie im Source Beispiel...

baumina 20. Jan 2014 14:52

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Welcher Datentyp wird dir denn bei dem sum-Feld angezeigt?
Delphi-Quellcode:
aDS.FieldByName('SumMenge').Datatype

p80286 20. Jan 2014 15:22

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Zitat:

Zitat von Andidreas (Beitrag 1244552)
Mittlerweile hab ichs auf den Feldtyp "int" umgestellt.

Dann sollte eigentlich jedes
Code:
select * from MyTabelle order by 1
das erwartete Ergebnis bringen.

Zitat:

Zitat von Andidreas (Beitrag 1244552)
Betrachte ich meine SQLite Tabelle mit dem SQLiteManager Add-On im Firefox werden die Daten durch ein "Order By" richtig sortiert.

Jo, so ist es ja auch richtig

Zitat:

Zitat von Andidreas (Beitrag 1244552)
Sortiere ich im Programm über die UniDac Komponente mit einem "Order By" habe ich wieder das beschriebene Problem das er nicht richtig sortiert.
Dasselbe habe ich wenn ich nach einem Klick auf die Spalten Überschrift mit "IndexFieldName" sortiere.

Wenn Die Daten nach einem "Select ... order by .." abgeholt werden, ist das ein sehr ungewöhnliches verhalten.
Ich nehme eher an, daß Du die Daten, die bereits angezeigt wurden, und jetzt nicht mehr numerisch sind, versuchst zu sortieren. Und das geht zunächst einmal nicht.

Eine Krücke wäre es wenn Du explizit führende Nullen oder Leerzeichen einfügst. dann sollte es wie "richtig sortiert" aussehen.

Aber der wahre Jakob ist das nicht!

Gruß
K-H

Andidreas 20. Jan 2014 15:39

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Zitat:

Zitat von baumina (Beitrag 1244561)
Welcher Datentyp wird dir denn bei dem sum-Feld angezeigt?
Delphi-Quellcode:
aDS.FieldByName('SumMenge').Datatype

Das SUM Feld wird als String angegeben bzw. zurückgegeben.
Das erklärt nun den Fehler!
Aber woher kommt der? Von der UniDac Query? Oder von der SQLite DB?

Zitat:

Zitat von p80286 (Beitrag 1244563)
Wenn Die Daten nach einem "Select ... order by .." abgeholt werden, ist das ein sehr ungewöhnliches verhalten.
Ich nehme eher an, daß Du die Daten, die bereits angezeigt wurden, und jetzt nicht mehr numerisch sind, versuchst zu sortieren. Und das geht zunächst einmal nicht.

Eine Krücke wäre es wenn Du explizit führende Nullen oder Leerzeichen einfügst. dann sollte es wie "richtig sortiert" aussehen.

Aber der wahre Jakob ist das nicht!

Gruß
K-H

Ja die Daten wurden bereits angezeigt. Und nach einem Klick auf die Spalten Überschrift versuche ich nun die Daten zu Sortieren, in der TUniQuery über IndexFieldNames.

An das mit den führenden Nullen dachte ich auch schon, aber so schön würde ich die Lösung nicht finden, vor allem da sie auch nicht User freundlich ist...

baumina 21. Jan 2014 06:31

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Schau mal hier, falls du es noch nicht selber gefunden hast : http://forums.devart.com/viewtopic.php?t=20670

Andidreas 21. Jan 2014 07:38

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Ich war gestern im DevArt Forum unterwegs und hab gesucht, auf den Artikel bin ich aber nicht gestoßen, Vielen Dank! :thumb:

Leider haben die damals ja auch keine praktikable lösung gefunden :pale:

Mal schaun ob mein eigener Topic mehr Erfolg hat im DevArt Forum...

baumina 21. Jan 2014 07:43

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Nur falls es dich interessiert : Ich benutze UniDAC mit mysql, dort werden mir alle sum-Felder als ftFloat gegeben.

Andidreas 21. Jan 2014 07:49

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Wie kann ich den denn DataType eines Feldes in eine String Variable einlesen?

baumina 21. Jan 2014 07:58

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Delphi-Quellcode:
S := FieldTypeNames[aDB.FieldByName('FeldName').DataType];


EDIT : Du könntest als WorkAround mal versuchen eine temporäre Tabelle anzulegen und dort das Summenfeld als Integer definieren. Danach deinen select in diese Tabelle als insert durchführen, evtl. klappt das ja.

Andidreas 21. Jan 2014 08:32

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Zitat:

Zitat von p80286 (Beitrag 1244563)
Eine Krücke wäre es wenn Du explizit führende Nullen oder Leerzeichen einfügst. dann sollte es wie "richtig sortiert" aussehen.

Das mit den führenden Nullen is au net so s wahre...
Selbst wenn ich in der SQLite wieder ein Text Feld habe in dem die Mengen mit führenden Nullen stehen entfernt mir mein SUM() diese wieder und ich steh wieder vor dem Problem das ich einen String habe und nicht richtig sortieren kann...

Andidreas 21. Jan 2014 09:07

AW: SQLite + DBGrid + Sortieren über Spalten Click
 
Also nach bisl Testerei hab ich jetzt die folgenden Lösung (hätte ich auch früher drauf kommen können)...

Ich habe vorhin festgestellt das wenn ich mein summiertes Mengen Feld (welches als Integer in der Datenbank definiert ist) über den Alias Namen in der Order By Klausel sortiere, dass ich dann das richtige Sortier Ergebnis erhalte.
Also habe ich mich jetzt gegen die "IndexFieldName" Funktion der TUniQuery entschieden und sortiere im OnTitleClick des DBGrids wieder über einen SQL Befehl (ich denke die Lösung ist vertretbar, da meine SQLite auf dem Client liegt und so kein Unterschied entsteht ob ich auf dem Client die Ergebnis Menge sortiere oder mir das Ergebnis neu sortiert hole)

Meiner Meinung nach ist in der DevArt Komponente ein Bug und es ist nicht ein Fehler der SQLite Developer wie es AlexP im DevArt Forum (in dem Beitrag den baumina gepostet hat) darstellt...

Hier anbei mein Source für den Sort:
Delphi-Quellcode:

  //Get Sort Column Number and Name
  If Column.Index = giSortColumn Then
  Begin
    If gsSortOrder = 'ASC' Then gsSortOrder := 'DESC' Else gsSortOrder := 'ASC';
  End Else
  Begin
    gsSortOrder := 'ASC';
  End;

  giSortColumn := Column.Index;
  sFieldName := Column.FieldName;


  //Sort via SQL
  Try
    With (sqlitefile_query1) Do
    Begin
      Active := False;
      datsrc_test.DataSet := Nil;
      SQL.Clear;
      SQL.Add('Select ');
      SQL.Add('COMMON, COM_NO, COM_KZ, SUM(COMSTT) as "Test" ');
      SQL.Add('From DATCOM ');
      SQL.Add('Group By COMMON, COM_NO, COM_KZ ');
      SQL.Add('Order By ' + sFieldName + ' ' + gsSortOrder);
      datsrc_test.DataSet := sqlitefile_query1;
      Active := True;
    End;
  Except
    On E:Exception Do
    Begin
      MessageDlg(E.Message, mtError, [mbOK], 0);
      Exit;
    End;
  End;


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:09 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz