Besat
Besat

Reputation: 1438

How to get distinct result based on one field from core data

My core data table is something like this:

enter image description here

I would like to get latest messages from each sender. so the results should be like:

enter image description here

this is my code:

    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"MyCoreDataObject" inManagedObjectContext:moc];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"MESSAGE <> ''"];

    request.predicate = predicate;
    NSSortDescriptor *sd1 = [[NSSortDescriptor alloc] initWithKey:@"TIME" ascending:NO];
    NSArray *sortDescriptors = @[sd1];
    [request setSortDescriptors:sortDescriptors];
    [request setEntity:entityDescription];
    NSError *error;
    NSArray *msgs = [moc executeFetchRequest:request error:&error];

I will get all sorted data (latest message first). But how can I get unique values based on sender? So only latest message for each sender?

Basically I need equivalent of this SQL:

SELECT message, sender, MAX(time) as maxTime FROM myTable GROUP BY sender;

Upvotes: 1

Views: 378

Answers (1)

Besat
Besat

Reputation: 1438

Getting message field was the hard part.

Basically if you use group by you can only fetch the properties in the group by (sender) and properties with expression (time).

To get all other values you need to use the fetched values (sender and time) and perform another fetch to get it from core data.

NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"MyCoreDataObject" inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"message <> ''"];

request.predicate = predicate;
NSSortDescriptor *sd1 = [[NSSortDescriptor alloc] initWithKey:@"time" ascending:NO];
NSArray *sortDescriptors = @[sd1];
[request setSortDescriptors:sortDescriptors];
[request setEntity:entityDescription];

NSExpressionDescription *timestampExp = [[NSExpressionDescription alloc] init];
[timestampExp setExpression:[NSExpression expressionWithFormat:@"@max.time"]];
[timestampExp setName:@"time"];
[timestampExp setExpressionResultType:NSDateAttributeType];

[request setSortDescriptors:sortDescriptors];
[request setEntity:entityDescription];
[request setResultType:NSDictionaryResultType];
[request setPropertiesToGroupBy:[NSArray arrayWithObject:@"sender"]];
[request setPropertiesToFetch:[NSArray arrayWithObjects:@"sender", timestampExp, nil]];

NSError *error;
NSArray *msgs = [moc executeFetchRequest:request error:&error];
for (NSDictionary *msg in msgs) {
    request = [[NSFetchRequest alloc] init];
    predicate = [NSPredicate predicateWithFormat:@"message <> '' and sender = %@ and time = %@ ", msg[@"sender"], msg[@"time"]];

    request.predicate = predicate;
    [request setSortDescriptors:sortDescriptors];
    [request setEntity:entityDescription];
    NSDictionary *myMessage = [moc executeFetchRequest:request error:&error][0];

}

Upvotes: 2

Related Questions