Последняя версия DataExpress 3 beta от 2 ноября 2018 года. Скачать. Энциклопедия DX. Форум на Develop-Soft

TdxForm.OpenRecord/s

Вопросы о применении того или иного класса или функции.
Аватара пользователя
Гocть
Эксперт
Сообщения: 1265
Зарегистрирован: Пн ноя 27, 2017 8:02 am

TdxForm.OpenRecord/s

Сообщение Гocть » Пт сен 14, 2018 3:52 pm

Имеется некий массив полученный в результате SQL-запроса и содержит ID для отбора записей. Выглядит примерно так:
[1,2,3...9 999,10 000] с пропуском всего одного значения. Например 655. То есть необходимо открыть 9 999 записей из 10 000.
Вариант выполнить OpenRecords(фильтр с применением данных из массива) не прокатил из за длины текста (динамически сформированная строка вида [ПолеID]=arr[№] | *** в тесте превысила длину >65535 символов), пробовал эксперимент: OpenRecord(очередное значение массива) в цикле, тоже не помогло (надо ж было попробовать :) ).
Какие еще есть варианты передачи подобного объема в фильтр TdxForm (иные способы открытия списка по указанному условию?)?
Фрилансер. Разработка на заказ. Консультирование.

Аватара пользователя
admin
Разработчик
Сообщения: 3898
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская

Re: TdxForm.OpenRecord/s

Сообщение admin » Пт сен 14, 2018 5:44 pm

Значит надо как-то сокращать условие. Зачем сравнивать огромный массив идущих подряд значений, если можно использовать операции "больше" и "меньше". Если есть пропуски то разбивать на несколько подусловий.

Аватара пользователя
Гocть
Эксперт
Сообщения: 1265
Зарегистрирован: Пн ноя 27, 2017 8:02 am

Re: TdxForm.OpenRecord/s

Сообщение Гocть » Пт сен 14, 2018 6:47 pm

"Большие пропуски" это то, чего нет в таблице. Речь о полнотекстовом поиске по всем полям.
Формирую вот такой текст запроса:

Код: Выделить всё

for k:=0 to fm.ComponentCount-1 do
    begin
      if GetComponentId(fm.Components[k])=0 then Continue else
        if sf = '' then
          sf:=sf+' where (lower(cast('+'F'+
          IntToStr(GetComponentId(fm.Components[k]))+
          ' as CHARACTER(20))) like lower(''%'+text+'%''))'
        else
          sf:=sf+' or '+#13#10+'(lower(cast('+'F'+
          IntToStr(GetComponentId(fm.Components[k]))+
          ' as CHARACTER(20))) like lower(''%'+text+'%''))';
    end;
    QT:=SQLSelect('select * from T'+IntToStr(fm.ID)+sf);   

= текст запроса:

Код: Выделить всё

select * from T1 where (lower(cast(F1 as CHARACTER(20))) like lower('%какой то текст%')) or
(lower(cast(F2 as CHARACTER(20))) like lower('%какой то текст%')) or
(lower(cast(F5 as CHARACTER(20))) like lower('%какой то текст%')) or
(lower(cast(F7 as CHARACTER(20))) like lower('%какой то текст%')) or
(lower(cast(F8 as CHARACTER(20))) like lower('%какой то текст%')) or
(lower(cast(F9 as CHARACTER(20))) like lower('%какой то текст%')) or
(lower(cast(F10 as CHARACTER(20))) like lower('%какой то текст%')) or
(lower(cast(F12 as CHARACTER(20))) like lower('%какой то текст%'))


выполняем. Из 10k записей получается лишь одна НЕ содержит "какой то текст". Значт надо забрать 9999, они ведь наши по праву:

Код: Выделить всё

// var QT:TdxSQLQuery

QT.MoveFirst;
    while not QT.EoF do
    begin
    // и тут Остапа понесло:
    if QT.BoF  then
    filter:='[!ID]='+IntTostr(QT.Field[0].AsInteger) else
    filter:=filter+'|[!ID]='+IntTostr(QT.Field[0].AsInteger); // dynamic filter pisec
    QT.MoveNext;
       //debug(filter)
    end;
    //if Trim(filter)='' then
    //fm.openRecord(0) else
    //fm.openRecords(filter,true);
  end;             


Пыщь. По результатам теста подобный фильтр самоубился с ростом количества записей.

И все. Нельзя вот так просто сделать 1). Self := QT, 2). Self.Grid.Refresh (это было бы слишком просто :lol: ).
Фрилансер. Разработка на заказ. Консультирование.

Аватара пользователя
admin
Разработчик
Сообщения: 3898
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская

Re: TdxForm.OpenRecord/s

Сообщение admin » Пт сен 14, 2018 7:24 pm

Не могу понять суть этих манипуляций. Просто составить фильтр для OpenRecords разве не получается? Это продолжение темы, из-за "0"?

Аватара пользователя
Гocть
Эксперт
Сообщения: 1265
Зарегистрирован: Пн ноя 27, 2017 8:02 am

Re: TdxForm.OpenRecord/s

Сообщение Гocть » Пт сен 14, 2018 7:38 pm

admin писал(а):Это продолжение темы,?

Это продолжение полнотекстового поиска (про поле в форме со склейкой помню, но нужна pluq&play функция типа drts-поиск). А тема просто стала напоминанием.
admin писал(а):Просто составить фильтр для OpenRecords разве не получается?

Проблема в том, что фильтр в OpenRecords работает через парсер, который не дает нормально развернуть опции поиска (чистый SQL рулит).
Фрилансер. Разработка на заказ. Консультирование.

Аватара пользователя
admin
Разработчик
Сообщения: 3898
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская

Re: TdxForm.OpenRecord/s

Сообщение admin » Пт сен 14, 2018 7:53 pm

Отбирайте в запросе только поле, обеспечивающее уникальность записи. Счетчик к примеру. Дальше определяйте непрерывные цепочки значений и составляйте условия больше/меньше. Например, запрос возвращает значения: 1, 2, 3, 5, 6, 9, 10, 11. А в OpenRecords пойдет условие: [поле] >= 1 & [поле] <= 3 | [поле] >= 5 & [поле] <= 6 | [поле] >=9 & [поле] <= 11.

Аватара пользователя
Гocть
Эксперт
Сообщения: 1265
Зарегистрирован: Пн ноя 27, 2017 8:02 am

Re: TdxForm.OpenRecord/s

Сообщение Гocть » Пт сен 14, 2018 8:04 pm

В примере выше я почти так и сделал (дубликат recid в поле [ID] сравниваем с QT.Field[0]) за исключением функции обхода диапазонов больше/меньше). Идея с цепочками конечно неплохая, но она лишь сократит тот текст, который своей длиной может однажды сломать запрос (например при выборе из объемного справочника типа кладр или фиас, где буковка "м" вернет диапазон [1(можайск)..100 000(малый бобруйск)]). Печалька, что нельзя просто присвоить полученные данные из TdxSQLQuery в TdxForm.
Ну и такой факт:
admin писал(а):Отбирайте в запросе только поле, обеспечивающее уникальность записи. Счетчик к примеру.
Гocть писал(а):дубликат recid в поле [ID]
не дает сделать нормальную "транспортабельную" функцию ВставьИПользуйся, несмотря на то, что в API уже практически ко всему есть доступ. Можно вообще в форму вынести ID в виде статичного скрытого (ключевого) поля? А то выходит, что стремление к простоте для конечного пользователя разработчика наоборот все усложняет в построении выражений (буквально сегодня в сотый очередной раз возникал вопрос).
Фрилансер. Разработка на заказ. Консультирование.

Аватара пользователя
admin
Разработчик
Сообщения: 3898
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская

Re: TdxForm.OpenRecord/s

Сообщение admin » Пт сен 14, 2018 8:56 pm

Гocть писал(а):Идея с цепочками конечно неплохая, но она лишь сократит тот текст, который своей длиной может однажды сломать запрос

Знаю. Что еще предложить?..Можно еще TKGrid заполнять.
Гocть писал(а):Можно вообще в форму вынести ID в виде статичного скрытого (ключевого) поля?

Честно говоря, мне неохота раздувать код программы ради ID. Я не вижу никаких проблем использовать для этих целей счетчик.

Аватара пользователя
Гocть
Эксперт
Сообщения: 1265
Зарегистрирован: Пн ноя 27, 2017 8:02 am

Re: TdxForm.OpenRecord/s

Сообщение Гocть » Пт сен 14, 2018 9:09 pm

admin писал(а):использовать для этих целей счетчик.

Счетчик скинули и пыщь :shock: .
Фрилансер. Разработка на заказ. Консультирование.

Аватара пользователя
admin
Разработчик
Сообщения: 3898
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская

Re: TdxForm.OpenRecord/s

Сообщение admin » Сб сен 15, 2018 7:33 am

Его скинуть можно только по собственному желанию и разумению. Если сильно захотеть, то и ID скинуть можно.


Вернуться в «Вопросы по API DataExpress.»