核心数据 - 与条件的嵌套总和

时间:2013-01-14 17:15:43

标签: ios objective-c core-data

我有一个应用程序,显示商店一直销售的金额。

NSNumber *amount = [self valueForKeyPath:@"sales.@sum.value"];

现在我必须过滤并按周期显示金额。我有持有月份和年份的字段“句号”(字符串),如“2012-11”。

如何使用where子句进行相同的查询?

1 个答案:

答案 0 :(得分:2)

您可以在计算总和之前过滤销售额。

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"period == %@", @"2012-11"];
NSSet *sales = [self valueForKeyPath:@"sales"];
NSSet *filteredSales = [sales filteredSetUsingPredicate:predicate];
NSNumber *amount = [filteredSales valueForKeyPath:@"@sum.value"];

但是当你有几十个或更多的销售额时,这种方法效率不高,因为它需要将每笔销售加载到内存中。

此外,如果销售有问题,每次销售都将fire a fault并生成SQL请求。您可以在过滤前通过batch faulting销售来阻止此操作。

我们假设self是一个托管对象。

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"period == %@", @"2012-11"];
NSSet *sales = [self valueForKeyPath:@"sales"];
// Begin batch-faulting
NSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *request = [NSFetchRequest new];
[request setEntity:[NSEntityDescription entityForName:@"Sale" inManagedObjectContext:moc]];
[request setPredicate:[NSPredicate predicateWithFormat:@"self IN %@", sales]];
[request setReturnsObjectsAsFaults:NO];
[moc executeFetchRequest:request error:NULL];
// Batch-faulting done
NSSet *filteredSales = [sales filteredSetUsingPredicate:predicate];
NSNumber *amount = [filteredSales valueForKeyPath:@"@sum.value"];

但是,您仍然会为每次销售(托管对象,其缓存及其属性)获得多个分配。最好的解决方案是使用获取请求来计算SQLite数据库中的总和。

NSString *reverseRelationship = @"store"; // name of the relationship from the sale to self
NSExpressionDescription *description = [NSExpressionDescription new];
[description setName:@"amount"];
[description setExpressionResultType:NSDoubleAttributeType];
[description setExpression:[NSExpression expressionWithFormat:@"@sum.value"]];
NSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *request = [NSFetchRequest new];
[request setEntity:[NSEntityDescription entityForName:@"Sale" inManagedObjectContext:moc]];
[request setResultType:NSDictionaryResultType];
[request setPredicate:[NSPredicate predicateWithFormat:
                       @"%K == %@ AND period == %@", reverseRelationship, self, @"2012-11"]];
[request setPropertiesToFetch:@[description]];
NSDictionary *result = [[moc executeFetchRequest:request error:NULL] lastObject];
NSNumber *amount = [result objectForKey:@"amount"];