如何将此 SQL 查询转换为 NSFetchRequest
Posted
技术标签:
【中文标题】如何将此 SQL 查询转换为 NSFetchRequest【英文标题】:How to translate this SQL Query into a NSFetchRequest 【发布时间】:2014-11-07 20:30:11 【问题描述】::
select max(ZSENTAT), * from ZMESSAGE where ZISINCOMING == 1 group by ZROOTMESSAGEID;
这是我走了多远:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isIncoming == %@ AND sentAt == @max.sentAt", [NSNumber numberWithBool:YES]];
NSFetchRequest *request = _fetchedResultsController.fetchRequest;
request.predicate = predicate;
request.propertiesToGroupBy = @[ @"rootMessageId" ];
这会导致异常:'NSInvalidArgumentException',原因:'带有 GROUP BY 组件的查询中的 SELECT 子句只能包含在 GROUP BY 或聚合函数中命名的属性
谢谢 克里斯
【问题讨论】:
谓词不等同于 SQL。 【参考方案1】:出现错误是因为您需要将提取限制为仅“分组依据”和任何聚合函数中的那些属性。在您的情况下,您需要将其限制为 rootMessageId
和 max(sentAt)
。为此,您必须指定NSFetchRequest
的propertiesToFetch
。 注意,如果您这样做,则必须将其 resultType
指定为 NSDictionaryResultType
,这将限制您使用 NSFetchedResultsController
的更改跟踪(即委托方法)。
如果您确实想实现获取:指定 rootMessageId 很容易,指定 max(sentAt) 需要更多的工作。您必须创建一个NSExpression
和NSExpressionDescription
。请查看 Apple 文档以了解这些内容,但以下内容应该可以帮助您入门:
NSExpression *maxExpression = [NSExpression expressionWithFormat:@"max:(sentAt)"];
NSExpressionDescription *maxDesc = [[NSExpressionDescription alloc] init];
maxDesc.name = @"maxSentAt";
maxDesc.expression = maxExpression;
maxDesc.expressionResultType = NSDateAttributeType; // I assume sentAt is a NSDate
request.propertiesToFetch = @[@"rootMessageId", maxDesc];
request.propertiesToGroupBy = @[@"rootMessageId"];
request.resultType = NSDictionaryResultType;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isIncoming == %@",[NSNumber numberWithBool:YES]];
request.predicate = predicate;
NSArray *results = [self.managedObjectContext executeFetchRequest:request error:&error];
etc
结果数组将包含具有两个键的字典:“rootMessageId”和“maxSentAt”。
【讨论】:
感谢您的精彩解释。还有 2 件事:我怎样才能仍然获得所选实体的所有字段?你能给我一些关于如何有效替换 NSFetchedResultsController 并仍然跟踪变化的指导吗? KVO/事件? 如果你想要额外的字段,我会放弃propertiesToGroupBy
(也许你已经有了!)。你能修改你的模型,包括一个“最近的”属性(然后你必须管理它)吗?或者,您能否将rootMessageId
指定为您的获取结果控制器的sectionKeyName
,您的获取按rootMessageId
和sentAt
排序,然后只使用每个部分中的第一项?以上是关于如何将此 SQL 查询转换为 NSFetchRequest的主要内容,如果未能解决你的问题,请参考以下文章