DELPHI - нужна помощь с ClientDataSet - PullRequest
0 голосов
/ 17 марта 2009

У меня есть ClientDataSet со следующими данными

IDX   EVENT BRANCH_ID   BRANCH
1     E1     7  B7
2     E2     5  B5
3     E3     7  B7
4     E4     1  B1
5     E5     2  B2
6     E6     7  B7
7     E7     1  B1

Мне нужно преобразовать эти данные в

IDX   EVENT BRANCH_ID   BRANCH
1     E1     7  B7
2     E2     5  B5
4     E4     1  B1
5     E5     2  B2

Единственными важными полями являются BRANCH_ID и BRANCH. и BRANCH_ID должен быть уникальным

Поскольку данных много, я не знаю, какие из них имеют копии.

ВОПРОС : Можете ли вы предложить способ преобразования данных с использованием клонированной версии исходных данных?

Ответы [ 3 ]

1 голос
/ 17 марта 2009

Я не могу придумать хитрый способ сделать это, но вы можете проиндексировать BRANCH_ID, добавить логическое поле fkInternalCalc в ваш набор данных, а затем инициализировать это поле в True в первой строке каждой ветви (используя состояние группы или вручную), а затем отфильтруйте клон по значению поля. Вы должны обновить поле об изменениях данных, хотя.

Мне кажется, что лучшим решением было бы иметь основной набор данных со строкой для каждой ветви.

1 голос
/ 17 марта 2009

Клонирование не позволит вам на самом деле изменять данные в клоне и не будет отражать те же изменения в оригинале, поэтому, если вы этого хотите, вы можете переосмыслить идею клонирования.

Клонирование дает вам отдельный курсор в клоне и позволяет вам фильтровать и индексировать (то есть упорядочивать) его независимо от основного набора данных клиента. Исходя из предоставленных вами данных, похоже, что вы хотите отфильтровать некоторые данные и порядок ветвления по branch_id. Вы можете сделать это, установив новый фильтр и индекс для клона. Вот хорошая статья, которая включает примеры того, как это сделать:

http://edn.embarcadero.com/article/29416

Если еще раз взглянуть на ваш вопрос, кажется, что все, что вам нужно, это установить уникальный индекс для branch_id для клонированного набора данных. Связанная статья выше содержит информацию о том, как настроить индекс; проверьте документацию по функции clientdataset.addindex для получения более подробной информации и информации о настройке индекса для показа только уникальных значений, если я напомню, это может означать, что вы установили branch_id как первичный ключ.

0 голосов
/ 18 марта 2009

Вы не предоставляете много подробностей о вашем случае использования, поэтому я постараюсь дать вам несколько советов:

  1. «Много данных» предполагает, что вы можете получить их из бэкэнда SQL. Использование «SELECT DISTINCT ...» или «SELECT ... GROUP BY BRANCH_ID» (или аналогичного синтаксиса в зависимости от того, какой бэкэнд SQL вы делаете) даст желаемый результат с легкостью и скоростью. Пожалуйста, подтвердите, и я дам вам более подробную информацию.

  2. Как и другие говорили, простой клон не сработает. Самое простое (и, возможно, более быстрое) решение, если предположить, что обычно количество WRT данных мало, - это иметь индекс вне вашего набора данных. Если вы действительно хотите отфильтровать исходные данные, добавьте в свои данные поле состояния (например, логическое) и установите флаг (например, «True») в первый раз.

псевдокод: (Давайте предположим, что: ваш ClientDataSet - cds1 у вашего cds1 есть поле состояния cds1Status (логическое значение) - это необязательно, необходимо только если вы хотите отсортировать / отфильтровать / найти cds1 у вас есть индекс, который является TStringList)

lIndex.Clear;
lIndex.Sorted:=True; 

with cds1 do
try
  DisableControls;
  First;
  while not Eof do //scan the dataset
  begin
    cVal:=cds1Branch_ID.AsString;
    Edit; //we anyway update the Status field
    if lIndex.Find(cVal, nDummy) then //nDummy - we don't use it. 
    begin //already in index
      cds1Status.AsBoolean:=False; //we say here "No, isn't the 1st occurence"
    end
    else
    begin //Not found! - Well, let's add it...
      lIndex.Append(cVal); //update the index 
      cds1Status.AsBoolean:=True; //mark the first occurence
    end;
    Post; //save the changes in the status field
    Next;
  end; //scan
finally
  EnableControls; //housekeeping
end;

// ВНИМАНИЕ! - Не испытано. Я написал это из своей головы, но я думаю, что у вас есть идея ...

... В зависимости от того, что вы пытаетесь достичь (что было бы лучшим, что вы могли бы поделиться с нами) и какой избирательности вы обладаете для BRANCH_ID, возможно, механизм статуса вообще не нужен. Если у вас очень низкая селективность в этом поле (селективность = число уникальных значений / количество записей), возможно, гораздо быстрее получить новый набор данных и скопировать туда только уникальные значения, а не помещать каждую запись оригинальных компакт-дисков в Редактировать + Опубликовать состояния. (Изменение состояний набора данных является дорогостоящей операцией. Особенно, если ваши компакт-диски связаны с удаленным хранилищем данных - т.е. сервером).

НТН,

PS: мое решение должно быть в основном простым. Также вы можете протестировать с lIndex.Sorted: = False и использовать lIndex.IndexOf вместо Find. В некоторых (редких) случаях лучше. Зависит от ваших данных. Если вы хотите все усложнить, и скорость действительно вызывает беспокойство, вы можете реализовать полноценный индекс BTree для поиска (библиотеки доступны). Также вы можете использовать механизм индексации CDS, индексировать BRANCH_ID и делать много «Определений» для клона, но поскольку ваша избирательность явно <1, сканирование всего индекса компакт-диска теоретически должно быть медленнее, чем сканирование уникального индекса, особенно если ваш индивидуальный индекс с учетом вашего типа данных, структуры, распределения и т. д. </p>

просто my2c

...