-1

次のデータを持つ 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 は一意である必要があります

たくさんのデータがあるので、私はそれのコピーを 2 つ持っていません。

質問:元のデータのクローン バージョンを使用してデータを変換する方法を提案できますか?

4

3 に答える 3

1

これを行う巧妙な方法は考えられませんが、BRANCH_ID にインデックスを付け、fkInternalCalc ブール型フィールドをデータセットに追加し、各ブランチの最初の行でそのフィールドを True に初期化して (グループ状態を使用するか手動で)、次に、フィールドの値でクローンをフィルタリングします。ただし、データの変更時にフィールドを更新する必要があります。

より良い解決策は、ブランチごとに行を持つマスター データセットを用意することだと思います。

于 2009-03-17T17:08:31.403 に答える
0

ユースケースについて多くの詳細を提供していないため、いくつかのヒントを提供しようとします。

  1. 「大量のデータ」は、SQL バックエンドから取得した可能性があることを示唆しています。'SELECT DISTINCT...' または 'SELECT ... GROUP BY BRANCH_ID' (または SQL バックエンドに応じて同様の構文) を使用すると、目的の結果が簡単かつ迅速に得られます。確認してください。詳細をお知らせします。

  2. 他の人が言ったように、単純な「クローン」は機能しません。最も単純な (そしておそらくより迅速な) 解決策は、データに対する WRT の数が通常少数であると仮定すると、データセットの外部にインデックスを作成することです。元のデータを本当にフィルタリングしたい場合は、データにステータス フィールド (ブール値など) を追加し、最初に出現したものにフラグ (「True」など) を付けます。

PseudoCode: (仮定しましょう: ClientDataSet は cds1 で、cds1 にはステータス フィールド cds1Status (boolean) があります - これはオプションであり、cds1 をソート/フィルター/検索する場合にのみ必要です。TStringList である lIndex があります)

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 でどのような選択性を持っているかによって、ステータス エンジンはおそらくまったく必要ありません。そのフィールドの選択性が非常に低い場合 (選択性 = 一意の値の数 / レコードの数)、元の CD の各レコードを入れるよりも、新しいデータセットを作成して一意の値のみをそこにコピーする方がはるかに高速です。編集 + 投稿状態。(データセットの状態を変更することはコストのかかる操作です。特に、CD がリモート データ ストレージ (つまりサーバー) にリンクされている場合)。

h番目、

PS: 私のソリューションは、ほとんどが単純であることを意図しています。また、lIndex.Sorted:=False でテストし、Find の代わりに lIndex.IndexOf を使用することもできます。いくつかの(まれな)ケースでは、より良いです。あなたのデータに依存します。物事を複雑にしたい場合、速度が本当に問題になる場合は、本格的な BTree インデックスを実装して検索を行うことができます (利用可能なライブラリ)。また、CDS のインデックス エンジンを使用して BRANCH_ID のインデックスを作成し、クローンに対して多くの「検索」を実行できますが、選択性が明らかに 1 未満であるため、CD のインデックス全体をスキャンすることは理論的には一意のインデックスをスキャンするより遅くなるはずです。カスタムメイドのインデックスは、データ型、構造、分布などに合わせて調整されます。

my2cだけ

于 2009-03-18T06:28:55.950 に答える