NSPredicate用于按组选择具有最大值的行

时间:2011-09-20 11:25:30

标签: objective-c ios core-data

我正在使用Core Data以

的形式存储实体

TrackerEntry

  • 用户名
  • 时间戳

我想为每个用户选择最新记录。使用sql就像是

SELECT MAX(timestamp) FROM Log GROUP BY username

是否有创建NSPredicate来执行此操作?

2 个答案:

答案 0 :(得分:3)

我会使用NSExpression来做。下面的这段代码对你不起作用,因为你也必须按用户名进行分组,但这是最好的方法,无需取出所有内容。你想在db中执行max和group,而不是在内存中 - 因为它会更快:

NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];

// Expression for the max
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"timestamp"];

NSEntityDescription *entity = [NSEntityDescription entityForName:entityName
                                          inManagedObjectContext:self.coreDataStack.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setResultType:NSDictionaryResultType];

NSExpression *valueSumExpression = [NSExpression expressionForFunction:@"max:" arguments:[NSArray arrayWithObject:keyPathExpression]];

NSExpressionDescription *expressionDescription = [[[NSExpressionDescription alloc] init] autorelease];
[expressionDescription setName:@"maxTimestamp"];
[expressionDescription setExpression:valueSumExpression];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];

[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];

// Filter
//NSPredicate *pred = [NSPredicate predicateWithFormat:@" your predicate here"];
//fetchRequest.predicate = pred;

NSArray *results = [self.coreDataStack.managedObjectContext executeFetchRequest:fetchRequest error:nil];
if([results count] == 0) {

} else {

    // [[results objectAtIndex:0] valueForKey:@"maxTimestamp"];

}

答案 1 :(得分:0)

这对我有用,但它是一个循环。首先,您必须将唯一的名称放入数组中。

    NSFetchRequest *nameRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Log" inManagedObjectContext:self.managedObjectContext];
    nameRequest.entity = entity;
    nameRequest.resultType = NSDictionaryResultType;        
    [nameRequest setPropertiesToFetch:[NSArray arrayWithObject:[[entity propertiesByName] objectForKey:@"name"]]];
    NSArray *allNames = [self.managedObjectContext executeFetchRequest:nameRequest error:nil];
    names = [allNames valueForKeyPath:@"@distinctUnionOfObjects.name"];
    [nameRequest release];
    NSLog(@"%@", names);

效率不高或不方便。毕竟,Core Data不是数据库,而是对象图。

然后你可以遍历这些并获取最上面的一个。

    NSMutableArray *mutableResults = [NSMutableArray array];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.entity = [NSEntityDescription entityForName:@"Log" inManagedObjectContext:self.managedObjectContext];
    NSSortDescriptor *numberSort = [NSSortDescriptor sortDescriptorWithKey:@"number" ascending:NO];
    request.sortDescriptors = [NSArray arrayWithObject:numberSort];
    request.fetchLimit = 1;
    for (NSString *s in names) {
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"name = %@", s];
        request.predicate = pred;
        NSArray *results = [self.managedObjectContext executeFetchRequest:request error:nil];
        [mutableResults addObject:[results objectAtIndex:0]];
    }
    [request release];
    NSLog(@"%@", mutableResults);