I'm using the following in my CommandText
property of the DataSet
I'm using:
SELECT *
FROM table_name
ORDER BY FIELD(priority, 'urgent', 'normal'),
FIELD(state, 'wait', 'executed', 'done')
It should sort the data I'm displaying in the DBGrid
connected to this DataSet
, like this:
urgent
in the priority
column should start the DBGrid list.normal
in the priority
column,wait
in the state
column,executed
in the state
column,done
in the state
column.But It doesn't, well actually it kind of does, but it's actually backwards. Here is a quick video I've made to show you whats happening, maybe you can get a clearer view this way:
I'm guessing it's because of either the ID column
I'm using or the Date column
but if so, I have no idea how and why.
This is how those 2 columns look like/are set up:
I'm using RAD Studio 10 Seattle, dbExpress components (TSimpleDataSet, etc) and MySQL db
Any thoughts on how to fix this? thanks!
You are making life unnecessarily difficult for yourself going about it the way you are.
It's not necessary to get the server to do the sorting (by using an ORDER BY clause and it's arguably better to do the sorting in the client rather than on the server, because the client typically has computing power to spare whereas the server may not.
So, this is my suggested way of going about it:
Drop the ORDER BY from your SQL and just do a a SELECT * [...].
Replace your SimpleDataSet by a ClientDataSet and define persistent TFields on it. The reason for making this change is so as to be able to create two persistent fields of type fkInternalCalc.
In the TFields editor in the Object Inspector, define two fkInternalCalc fields called something like PriorityCode and StateCode.
Set the IndexFieldNames
property of your dataset to 'PriorityCode;StateCode'.
In the OnCalcFields event of your dataset, calculate values for the PriorityCode and StateCode that will give the sort order you wish the data rows to have.
Something like:
procedure TForm1.ClientDataSet1CalcFields(DataSet: TDataSet);
var
S : String;
PriorityCodeField,
StateCodeField : TField;
iValue : Integer;
begin
PriorityCodeField := ClientDataset1.FieldByName('PriorityCode');
StateCodeField := ClientDataset1.FieldByName('StateCode');
S := ClientDataset1.FieldByName('Priority').AsString;
if S = 'urgent' then
iValue := 1
else
if S = 'normal' then
iValue := 2
else
iValue := 999;
PriorityCodeField.AsInteger := iValue;
S := ClientDataset1.FieldByName('State').AsString;
if S = 'wait' then
iValue := 1
else
if S = 'executed' then
iValue := 2
else
if S = 'done' then
iValue := 3
else
iValue := 999;
StateCodeField.AsInteger := iValue;
end;
Actually, it would be better (faster, less overhead) if you avoid using FieldByName
and just use the fields that the Fields that the OI's Tfields editor creates, since these will be automatically bound to the ClientDataSet's data fields when it is opened.
Btw, it's useful to bear in mind that although a TClientDataSet cannot be sorted on a field defined in the TFields editor as Calculated
, it can be sorted on an InternalCalc
field.