2016-10-18 6 views
-1

Я использую следующие в моей CommandText собственности DataSet Я использую:DBGrid/DataSet не может сортировать согласно SQL заявление, установленного в CommandText

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

Он должен сортировать данные я отображающее в DBGrid, подключенного к этой DataSet, как это:

    1. Строки, содержащие urgent в priority столбец должен запустите список DBGrid.
    2. Затем список должен продолжать с теми, помеченными как normal в priority колонки
    1. следует, отмеченным как wait в state колонки,
    2. следует, отмеченным как executed в колонке state,
    3. и, наконец, список заканчивается на отметках done в столбце state.

Но это не так, а на самом деле это вид делает, но это на самом деле наоборот. Вот быстрое видео, которое я сделал, чтобы показать вам, Что происходит, может быть, вы можете получить более четкое представление таким образом:

Video of what's happening

Я предполагаю, что это из-за либо ID column я использую или Date column, но если да, я понятия не имею, как и почему.

Это как эти 2 колонки выглядят как/настроены:

enter image description here

  • ID столбец устанавливается в качестве начальной и Unique и AUTO_INCREMENT - это все, нет индекса или любой из других вариантов Если это не те 2 столбца проблемы, то, возможно, DBGrid?

Я использую RAD Studio 10 Сиэтл, DBEXPRESS компоненты (TSimpleDataSet и т.д.) и БД MySQL

Любые мысли о том, как это исправить? благодаря!

+0

Я никогда не использовал Field (в MySql до сих пор, но кажется, что вы используете его неправильно. Первый параметр для поля (функция должна быть целым числом). Вы не показываете, есть ли у вас поля с приоритетом или состоянием , но я думаю, что вы это сделали, или sql потерпит неудачу. Это не имеет ничего общего с Delphi. – nolaspeaker

+0

@nolaspeaker У меня есть столбцы с именем priority и state, значения ячеек для этих столбцов описаны выше (срочные, нормальные, ожидания и т. д.).). Столбцы с именем priority и state действительно настроены на VarChar, идентификатор столбца установлен как INT - вы говорите, что это может быть проблемой, и что 1-й столбец в используемом мне поле должен быть INT (в этом случае, приоритет?) – Petzy

+1

Предложите вам прочитать об использовании функции Field. – nolaspeaker

ответ

1

Вы делаете жизнь излишне трудной для себя, идя так, как вы.

Нет необходимости, чтобы сервер выполнял сортировку (с помощью предложения ORDER BY, и, возможно, лучше выполнять сортировку на клиенте, а не на сервере, поскольку клиент обычно имеет вычислительную мощность, чтобы сэкономить, тогда как сервер не может.

Итак, это мой Рекомендованный способ идти об этом:

  1. Отбросьте ORDER BY с вашего SQL и просто сделать ОТБОРНЫЙ * [...].

  2. Замените свой SimpleDataSet на ClientDataSet и определите на нем постоянные TFields. Причина этого изменения заключается в том, чтобы создать два постоянных поля типа fkInternalCalc.

  3. В редакторе TFields в Object Inspector определите два поля fkInternalCalc, которые называются PriorityCode и StateCode.

  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 и использовать только те поля, которые поля, создаваемые редактором Tfields ОИ, так как они будут автоматически привязаны к полям данных ClientDataSet при его открытии.

Btw, полезно иметь в виду, что хотя TClientDataSet не могут быть отсортированы по полю, определенной в редакторе TFields в Calculated, он может быть отсортированы по InternalCalc поле.

+0

* Huh * at "general принцип" ... –

+0

'' Это не обязательно чтобы заставить сервер выполнять сортировку «'. Что делать, если у вас есть миллионы записей в базе данных? вы все равно будете получать «SELECT *» клиенту и сортировать его там? Ваше решение/предложение * может * быть подходящим для OP , но он не отвечает на вопрос. – kobik

+0

@kobik: Ну, пользователь скоро узнает, что SimpleDataSet/ClientDataSet не может справиться с такими многими записями; =) – MartynA