I have a application that show the amount sold by a store all the time.
NSNumber *amount = [self valueForKeyPath:@"[email protected]"];
Now i have to filter and show the amount by period. I have the field "period" (string) that holds month and year, like "2012-11".
How can i make the same query using the where clause?
You can filter the sales before computing the sum.
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"period == %@", @"2012-11"];
NSSet *sales = [self valueForKeyPath:@"sales"];
NSSet *filteredSales = [sales filteredSetUsingPredicate:predicate];
NSNumber *amount = [filteredSales valueForKeyPath:@"@sum.value"];
But when you have many dozens or more sales, this method is not really efficient because it requires to load each sale into memory.
Moreover, if the sales are in fault, each sale will fire a fault and generate a SQL request. You may prevent this by batch faulting the sales before filtering them.
We will assume that self is a managed object.
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"];
However, you still get several allocations for each sale (the managed object, its cache, its attributes). The best solution is to use a fetch request to compute the sum in the SQLite database.
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"];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With