我在CommandText
我正在使用的DataSet
属性中使用以下内容:
SELECT *
FROM table_name
ORDER BY FIELD(priority, 'urgent', 'normal'),
FIELD(state, 'wait', 'executed', 'done')
它应该对与DBGrid
相关联的DataSet
中显示的数据进行排序,如下所示:
urgent
列中包含priority
的行应该启动DBGrid列表。normal
列中标记为priority
的列表,wait
列中标记为state
的executed
列中标记为state
的done
列中标记为state
的列表结束。但事实并非如此,但它确实是倒退的。 这是一个快速视频,我已经向您展示了发生了什么,也许您可以通过这种方式获得更清晰的视图:
我猜这是因为我正在使用ID column
或Date column
,但如果是这样,我不知道如何以及为什么。
这就是设置这两个列的方式:
我正在使用RAD Studio 10 Seattle,dbExpress组件(TSimpleDataSet等)和MySQL db
有关如何解决此问题的任何想法?谢谢!
答案 0 :(得分:1)
你正在以不自觉的方式让生活变得不必要。
没有必要让服务器进行排序(通过使用ORDER BY子句,在客户端而不是在服务器上进行排序可能更好,因为客户端通常具有计算能力,而服务器可能没有。
所以,这是我建议的解决方法:
从SQL中删除ORDER BY,然后执行SELECT * [...]。
用ClientDataSet替换SimpleDataSet并在其上定义持久性TField。进行此更改的原因是为了能够创建两个类型为fkInternalCalc的持久字段。
在Object Inspector的TFields编辑器中,定义两个名为PriorityCode和StateCode的fkInternalCalc字段。
将数据集的IndexFieldNames
属性设置为'PriorityCode; StateCode'。
在数据集的OnCalcFields事件中,计算PriorityCode和StateCode的值,这些值将提供您希望数据行具有的排序顺序。
类似的东西:
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;
实际上,如果你避免使用FieldByName
并且只使用OI的Tfields编辑器创建的Fields字段会更好(更快,更少开销),因为它们会自动绑定到ClientDataSet的数据字段当它被打开时。
顺便说一下,记住虽然TClientDataSet不能在TFields编辑器中定义的字段Calculated
上排序,但它可以在{{1}上排序,这很有用。 } field。