【发布时间】:2023-03-17 22:36:02
【问题描述】:
目前我有两个数据集。一个人拥有一组工作所需的所有文件;另一个有文件存在。我需要缺少的要求,即第一个数据集中不在第二个数据集中的文档。 (底层 SQL 数据结构中的问题阻止只查询丢失的文档而不使用过慢的子查询)。
我已尝试从所需的文档数据集中删除存在的文档,因此它只包含缺失的内容。
try
with cdsAllDocs do begin
while not eof do begin
cdsFilter(cdsRequiredDocs, 'JobID = ' + fieldByName('JobID').AsString + ' AND ID = ' + fieldByName('PREDEFINEDDOCID').AsString);
while cdsRequiredDocs.RecordCount > 0 do cdsRequiredDocs.Delete;
next;
end; // while not eof
end; // with cdsAllDocs
finally
cdsFilterClear(cdsRequiredDocs);
end;
我没有费心禁用控件,因为这两个数据集都没有任何关联的控件。
问题是这种方法非常慢。在需要约 7000 个文件的情况下,此过程需要约 2.25 秒才能获得我的精简列表。
有没有办法以更有效的方式做我想做的事情? (除了修复目前我无法控制的 SQL 数据)。谢谢。
以下几个cmets的添加: 一些人建议预先进行更好的查询可以获得单个数据集并首先避免此问题:以下是实际查询: 这个得到了所有要求的列表:
SELECT distinct
J.JobID,
P.PREDEFINEDDOCID as ID
FROM JOBTEMPLATECONTEXT JT
Join DEPARTMENTJOB DJ
on DJ.jobid = JT.JobID
and DJ.DepartmentJobFetch = "Y"
and UPPER(DJ.DEPARTMENTJOBSTATUS) in ("ACTIVE", "PENDING")
Join Job J
on JT.JOBID = J.JOBID
and J.JOBFETCH = "Y"
Join TEMPLATECONTEXT T
on T.TEMPLATECONTEXTID = JT.TEMPLATECONTEXTID
and JT.CONTEXTDUEDATE < "Now"
join PREDEFINEDDOC P on P.PREDEFINEDDOCID = T.TEMPCONTEXTID
而这个(非常慢)获取那里的文档:
SELECT distinct
J.JobID, P.PREDEFINEDDOCID
FROM Job J
Join JOBTEMPLATECONTEXT JT
on JT.jobid = J.JobID
and J.JobFetch = "Y"
Join DEPARTMENTJOB DJ
on DJ.JOBID = J.JOBID
and DJ.DepartmentJobFetch = "Y"
and UPPER(DJ.DEPARTMENTJOBSTATUS) in ("ACTIVE", "PENDING")
Join TEMPLATECONTEXT T
on T.TEMPLATECONTEXTID = JT.TEMPLATECONTEXTID
join PREDEFINEDDOC P on P.PREDEFINEDDOCID = T.TEMPCONTEXTID
join JOBDOCUMENTS JD
on JT.JOBID = JD.JOBID
join DOCUMENTS D
on D.PredefinedDocID = P.PREDEFINEDDOCID
and D.DOCUMENTFETCH = "Y"
and JD.DOCUMENTID = D.DOCUMENTID
请不要告诉我在 varChars 而不是枚举类型中存储我所限制的值是不好的,或者表的混乱是不好的数据库设计;我无法控制。
【问题讨论】:
-
我仍然会进行适当的初始查询。你能告诉我们数据库的类型、表结构和期望的结果吗?也许有人可以制定一个性能更好的查询。
-
@Eric 那么您在客户端数据集上显示的内容是:JobID = JobID 和 ID = PredefinedDocID 在表本身上是不可能的?是否有一些基于数据库外部数据的计算字段?
-
每个文档是否有唯一的数字文档 ID?我之所以问,是因为我想知道您是否以正确的方式进行此操作:在紧密循环中使用
FieldByName和RecordCount似乎不建议这样做。 -
所以我们的目标是让这样的东西以可接受的性能运行:
SELECT distinct J.JobID, P.PREDEFINEDDOCID as ID FROM JOBTEMPLATECONTEXT JT ... /* omitted for lack of space */ left outer join JOBDOCUMENTS JD on JT.JOBID = JD.JOBID left outer join DOCUMENTS D on D.PredefinedDocID = P.PREDEFINEDDOCID and D.DOCUMENTFETCH = "Y" and JD.DOCUMENTID = D.DOCUMENTID where D.DOCUMENTID IS NULL -
我感受到了你的痛苦。 :-/ 因此,如果您完全无法在客户端上处理它,您可以尝试在客户端数据集上创建一些索引。也正如@MartynA 所说,避免循环中的 FieldByName (在循环之前初始化本地 TField 变量)。
标签: delphi delphi-2010