DBGrid / DataSet 无法按照 CommandText 中设置的 sql 语句进行排序

DBGrid / DataSet fails to sort as per sql statement set in CommandText

我在 DataSetCommandText 属性 中使用以下内容:

SELECT *
FROM table_name
ORDER BY FIELD(priority, 'urgent', 'normal'),
         FIELD(state, 'wait', 'executed', 'done')

它应该对我在连接到此 DataSetDBGrid 中显示的数据进行排序,如下所示:

    1. priority 列中包含 urgent 的行应该开始 DBGrid 列表。
    2. 然后列表应该继续 priority 列中标记为 normal 的列表,
    1. 后面是 state 列中标记为 wait 的那些,
    2. 后面是 state 列中标记为 executed 的那些,
    3. 最后,列表以 state 列中标记为 done 的列表结尾。

但它并没有,事实上它有点,但它实际上是倒退的。 这是我制作的一个快速视频,向您展示发生了什么,也许您可​​以通过这种方式获得更清晰的视图:

Video of what's happening

我猜这是因为我正在使用 ID columnDate column 但如果是这样,我不知道如何以及为什么。

这 2 列看起来是这样 like/are 设置的:

我正在使用 RAD Studio 10 Seattle、dbExpress 组件(TSimpleDataSet 等)和 MySQL db

关于如何解决这个问题有什么想法吗?谢谢!

你正在为自己的生活增添不必要的困难。

没有必要让服务器进行排序(通过使用 ORDER BY 子句,并且可以说在客户端而不是在服务器上进行排序更好,因为客户端通常有空闲的计算能力,而服务器可能没有。

所以,这是我建议的处理方式:

  1. 从您的 SQL 中删除 ORDER BY 并执行一个 SELECT * [...].

  2. 用 ClientDataSet 替换您的 SimpleDataSet 并在其上定义持久 TFields。进行此更改的原因是为了能够创建两个 fkInternalCalc 类型的持久字段。

  3. 在对象检查器的 TFields 编辑器中,定义两个名为 PriorityCode 和 StateCode 的 fkInternalCalc 字段。

  4. 将数据集的 IndexFieldNames 属性 设置为 'PriorityCode;StateCode'。

  5. 在数据集的 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 编辑器创建的字段,那会更好(更快,开销更少),因为这些字段将自动绑定到 ClientDataSet 的打开时的数据字段。

顺便说一句,请牢记虽然 TClientDataSet 无法根据 TFields 编辑器中定义为 Calculated 的字段进行排序,但它 可以 进行排序InternalCalc 字段。