听起来你需要用SQL来完成你的目标。你的起始查询不会做你描述的事情,大多数数据库都不会接受它,因为聚合子查询试图选择一个不是组函数的列。
更新:
我最初认为请求是删除每个包含重复项的组中的所有成员,并相应地编写了代码。重新解释原始SQL,就像MySQL会做的那样,似乎目标是保留每个
(property1,property2,property3)
组合的一个元素。我想这更有意义。以下是一种标准方法:
delete from SomeTable st1
where someID not in (
select min(st2.someId)
from SomeTable st2
group by property1, property2, property3
)
使用min()
聚合函数来选择每个组中要保留的someId
值,这与原始内容有所不同。这也应该是有效的:
delete from SomeTable st1
where someID in (
select st3.someId
from SomeTable st2
join SomeTable st3
on st2.property1 = st3.property1
and st2.property2 = st3.property2
and st2.property3 = st3.property3
where st2.someId < st3.someId
)
这两个查询将保留相同的行。我更喜欢第二个,尽管它更长,因为对于从大型集合中选择少量元素来说,
NOT IN
运算符有点难搞。但是,如果您预计会有足够多的行涉及到缩放问题,那么您应该尝试两种方法,并考虑优化(例如,在
(property1,property2,property3)
上创建索引)和其他替代方案。
关于在Core Data调用术语中编写它,我认为你不能完全做到。Core Data支持分组,因此您可以编写Core Data调用以执行第一种选择中的子查询并返回实体对象或其ID,如所述进行分组。然后您可以遍历这些组,跳过每个组的第一个元素,并为所有其他元素调用Core Data删除方法。详细信息超出了SO格式的范围。
然而,我必须说,在Core Data中执行这样的工作比直接在数据库中执行要昂贵得多,无论是时间还是需要的内存。直接在数据库中执行此操作对ORM框架(如Core Data)不友好。这种情况是使用ORM框架所做的折衷之一。
我建议您尽可能避免这种需求。在
SomeTable(property1, property2, property3)
上定义唯一索引,并尽可能避免尝试创建重复项或从(失败的)尝试中恢复。
SomeTable.someId
是唯一的或者(更好的)是主键? - John Bollinger