DELPHI - 需要 ClientDataSet 的帮助

发布于 2024-07-15 09:18:36 字数 543 浏览 7 评论 0原文

我有一个包含以下数据的 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 必须是唯一的,

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

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

I have a ClientDataSet with the following data

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

I need to transform this data into

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

The only fields of importance are the BRANCH_ID and BRANCH
and BRANCH_ID must be unique

As there is a lot of data I do not what two have copies of it.

QUESTION:
Can you suggest a way to transfrom the data using a Cloned version of the original data ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

非要怀念 2024-07-22 09:18:36

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

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

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

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

Cloning won't allow you to actually change data in a clone and not have same change reflected in the original, so if that's what you want you might rethink the cloning idea.

Cloning does give you a separate cursor into the clone and allows you to filter and index (i.e. order) it independently of the master clientdataset. From the data you've provided it looks like you want to filter some branch data and order by branch_id. You can accomplish that by setting up a new filter and index on the clone. Here's a good article that includes examples of how to do that:

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

Taking a second look at your question, seems like all you'd need to do would be to set up a unique index on branch_id on the cloned dataset. Linked article above has info on how to set up index; check docs on clientdataset.addindex function for more details and info on setting the index to show only unique values, if I recall it may just mean you set branch_id as the primary key.

指尖上得阳光 2024-07-22 09:18:36

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

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

I can't think of a slick way to do this, but you could index on BRANCH_ID, add an fkInternalCalc boolean field to your dataset, then initialize that field to True on the first row of each branch (using group state or manually) and then filter the clone on the value of the field. You'd have to update the field on data changes though.

I have a feeling that a better solution would be to have a master dataset with a row for each branch.

謌踐踏愛綪 2024-07-22 09:18:36

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

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

  2. 正如其他人所说,简单的“克隆”是行不通的。 最简单(也许更快)的解决方案是在数据集之外建立一个索引,假设数据的括号数量通常很少。 如果您确实想过滤原始数据,请在数据上添加一个状态字段(例如布尔值),并在第一次出现时放置一个标志(例如“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 的选择性根本不需要 Status 引擎。 如果您对该字段的选择性非常低(选择性=唯一值的数量/记录的数量),那么拥有一个新数据集并仅复制唯一值而不是将原始CD的每个记录放入其中可能会更快编辑+发布状态。 (更改数据集状态是一项成本高昂的操作。特别是如果您的 CD 链接到远程数据存储 - 即服务器)。

hth,

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

只需 my2c

You don't provide many details about your use case so I'll try to give you some hints:

  1. "A lot of data" suggests that you might have it from a SQL backend. Using a 'SELECT DISTINCT...' or 'SELECT ... GROUP BY BRANCH_ID' (or similar syntax depending on what SQL backend do you) will give the desired result with ease and speed. Please confirm and I'll give you more details.

  2. As the others said a simple 'clone' wouldn't work. The most simpler (and perhaps quicker) sollution, assuming that ussually the brances are few in number WRT to data is to have an index outside of your dataset. If really you want to filter your original data then add a status field (eg boolean) on your data and put a flag (eg. 'True') on the first occurence.

PseudoCode:
(Let's asume that:
your ClientDataSet is cds1
your cds1 have a status field cds1Status (boolean) - this is optional, needed only if you want to sort/filter/search the cds1
you have a lIndex which is a 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;

//WARNING! - NOT tested. I wrote it from my head but I think that you got the idea...

...Depending on what you try to accomplish (which would be the best thing that you might share with us) and what selectivity do you have on BRANCH_ID perhaps the Status engine isn't needed at all. If you have a very low selectivity on that field (selectivity = no. of unique values / no. of records) perhaps it's much faster to have a new dataset and copy there only the unique values rather than putting each record of the original cds in Edit + Post states. (Changing dataset states are costly operations. Especially if your cds is linked to a remote data storage - ie. a server).

hth,

PS: My sollution is intended to be mostly simple. Also you can test with lIndex.Sorted:=False and use lIndex.IndexOf instead of Find. In some (rare) cases is better. Depends on your data. If you want to complicate the things and the speed is really a concern you can implement a full-blown BTree index to do your searces (libraries available). Also you can use the index engine of CDS and index the BRANCH_ID and do many 'Locate' on a clone but because your selectivity is clearly < 1 scaning the cds's entire index theorethically should be slower that a scan on a unique index, especially if your custom-made index is tailored to your data type, structure, distribuition etc.

just my2c

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文