DELPHI - 使用ClientDataSet提供帮助

时间:2009-03-17 16:32:21

标签: delphi tclientdataset

我有一个带有以下数据的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 个答案:

答案 0 :(得分:1)

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

克隆确实为您提供了一个单独的游标到克隆,并允许您独立于主clientdataset过滤和索引(即订购)它。根据您提供的数据,您似乎希望过滤某些分支数据并按branch_id排序。您可以通过在克隆上设置新的过滤器和索引来实现此目的。这是一篇很好的文章,其中包含如何执行此操作的示例:

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

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

答案 1 :(得分:1)

我想不出一个光滑的方法来做这个,但你可以在BRANCH_ID上索引,在数据集中添加一个fkInternalCalc布尔字段,然后在每个分支的第一行将该字段初始化为True(使用组状态或手动)然后过滤克隆字段的值。您必须更新数据更改字段。

我觉得更好的解决方案是拥有一个主数据集,每个分支都有一行。

答案 2 :(得分:0)

您没有提供有关您的用例的许多详细信息,因此我将尝试给您一些提示:

  1. “许多数据”表明您可能从SQL后端获得它。使用'SELECT DISTINCT ...'或'SELECT ... GROUP BY BRANCH_ID'(或类似的语法取决于你的SQL后端)将轻松快速地提供所需的结果。请确认,我会给你更多详细信息。

  2. 正如其他人所说,一个简单的'克隆'是行不通的。最简单(也许更快)的解决方案,假设通常数据WRT与数据的数量很少,就是在数据集之外有一个索引。如果您真的要过滤原始数据,请在数据上添加状态字段(例如布尔值),并在第一次出现时放置一个标记(例如“True”)。

  3. 伪代码: (让我们假设:  您的ClientDataSet是cds1  你的cds1有一个状态字段cds1Status(boolean) - 这是可选的,仅当你要对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的选择性,可能根本不需要Status引擎。如果你对该字段的选择性非常低(选择性=唯一值的数量/记录的数量),那么拥有一个新的数据集并且仅复制唯一值而不是将原始cds的每个记录放入其中的速度要快得多编辑+发布状态。 (更改数据集状态是昂贵的操作。特别是如果您的cds链接到远程数据存储 - 即服务器)。

    HTH,

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

    只是my2c