-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 必须是唯一的

由于有很多数据,我不知道哪两个有它的副本。

问题:您能否建议一种使用原始数据的克隆版本转换数据的方法?

4

3 回答 3

1

克隆不允许您实际更改克隆中的数据,并且不会在原始数据中反映相同的更改,因此如果您想要这样做,您可能会重新考虑克隆的想法。

克隆确实为您在克隆中提供了一个单独的光标,并允许您独立于主客户端数据集对其进行过滤和索引(即排序)。从您提供的数据来看,您似乎想要过滤一些分支数据并按 branch_id 排序。您可以通过在克隆上设置新的过滤器和索引来完成此操作。这是一篇很好的文章,其中包括如何做到这一点的示例:

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

再看看你的问题,似乎你需要做的就是在克隆数据集的 branch_id 上设置一个唯一索引。上面的链接文章有关于如何设置索引的信息;检查 clientdataset.addindex 函数上的文档以获取更多详细信息以及有关设置索引以仅显示唯一值的信息,如果我记得这可能只是意味着您将 branch_id 设置为主键。

于 2009-03-17T16:48:16.990 回答
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')。

伪代码:(假设:您的 ClientDataSet 是 cds1 您的 cds1 有一个状态字段 cds1Status(布尔值)-这是可选的,仅当您想要排序/过滤/搜索 cds1 时才需要,您有一​​个 lIndex,它是一个 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 的选择性,也许根本不需要状态引擎。如果您对该字段的选择性非常低(选择性=唯一值的数量/记录的数量),那么拥有一个新数据集并仅复制唯一值而不是将原始CD的每条记录放入其中要快得多编辑 + 发布状态。(更改数据集状态是昂贵的操作。特别是如果您的 cd 链接到远程数据存储 - 即服务器)。

h,

PS:我的解决方案主要是简单的。您也可以使用 lIndex.Sorted:=False 进行测试,并使用 lIndex.IndexOf 而不是 Find。在某些(罕见)情况下更好。取决于你的数据。如果您想让事情复杂化并且速度确实是一个问题,您可以实现一个成熟的 BTree 索引来执行您的搜索(可用的库)。您也可以使用 CDS 的索引引擎并索引 BRANCH_ID 并在克隆上执行许多“定位”,但是因为您的选择性显然 < 1,所以理论上扫描 cds 的整个索引应该比对唯一索引的扫描要慢,特别是如果您的定制索引是根据您的数据类型、结构、分布等量身定制的。

只是 my2c

于 2009-03-18T06:28:55.950 回答