如何将此 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】:

出现错误是因为您需要将提取限制为仅“分组依据”和任何聚合函数中的那些属性。在您的情况下,您需要将其限制为 rootMessageIdmax(sentAt)。为此,您必须指定NSFetchRequestpropertiesToFetch注意,如果您这样做,则必须将其 resultType 指定为 NSDictionaryResultType,这将限制您使用 NSFetchedResultsController 的更改跟踪(即委托方法)

如果您确实想实现获取:指定 rootMessageId 很容易,指定 max(sentAt) 需要更多的工作。您必须创建一个NSExpressionNSExpressionDescription。请查看 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,您的获取按rootMessageIdsentAt 排序,然后只使用每个部分中的第一项?

以上是关于如何将此 SQL 查询转换为 NSFetchRequest的主要内容,如果未能解决你的问题,请参考以下文章

如何将此 SQL 查询转换为 NSFetchRequest

如何将此 sql 查询转换为 mongodb?

如何将此 SQL 查询转换为 Django?

如何将此 SQL 内部联接查询转换为 LINQ 语法?

如何将此 SQL 转换为 Laravel Query Builder 查询?

如何将此 sql 查询转换为 laravel 查询生成器