GROUP BY equivalent for Core Data

后端 未结 4 665
离开以前
离开以前 2020-12-31 19:06

I know that I can use @distinctUnionOfObjects to find something like the following in SQL:

SELECT a_value
FROM my_table
GROUP BY a_value;

W

相关标签:
4条回答
  • 2020-12-31 19:11

    I find this method (roughly similar to the accepted answer) to be a little cleaner and easier to understand. This is the SQL equivalent to:

    SELECT COUNT(*), a_value FROM my_table GROUP BY a_value;

    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[MyTable className]];
    
    // create expression for grouped column
    NSExpressionDescription *aValueDescription = [[NSExpressionDescription alloc] init];
    aValueDescription.name = @"aValue"; // name of key in result dictionary
    aValueDescription.expression = [NSExpression expressionWithFormat:@"aValue"];
    aValueDescription.expressionResultType = NSObjectIDAttributeType;
    
    // create expression for count
    NSExpressionDescription *countDescription = [[NSExpressionDescription alloc] init];
    countDescription.name = @"count"; // name of dictionary key in result dictionary
    countDescription.expression = [NSExpression expressionWithFormat:@"aValue.@count"];
    countDescription.expressionResultType  = NSInteger32AttributeType;
    
    // fill out fetch request
    fetchRequest.propertiesToGroupBy = @[@"aValue"];
    fetchRequest.propertiesToFetch = @[aValueDescription, countDescription];
    //fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"count" ascending:NO]]; // not sure why this crashes
    fetchRequest.resultType = NSDictionaryResultType; // required for "group by" requests
    
    NSError *error = nil;
    NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
    

    The returned results is an array of NSDictionary. Note that the description name properties can be anything you want - they are just the names of the keys in the returned dictionaries. One can add a predicate to the fetch request to filter rows from the table; this code returns all rows.

    Bonus points to anyone who can tell me how to make the sort descriptor work...

    0 讨论(0)
  • 2020-12-31 19:17

    You can use Predicate Programming.

    EDIT: Sorry you can not use predicates for Group By at least not straight-forward. I just read on the references.

    Limitations: You cannot necessarily translate “arbitrary” SQL queries into predicates or fetch requests. There is no way, for example, to convert a SQL statement such as

    SELECT t1.name, V1, V2

    FROM table1 t1 JOIN (SELECT t2.name AS V1, count(*) AS V2
    
        FROM table2 t2 GROUP BY t2.name as V) on t1.name = V.V1
    
    0 讨论(0)
  • 2020-12-31 19:23

    It's analog

    SELECT 'Status', COUNT(*) FROM 'Records' GROUP BY 'Status':

    NSFetchRequest* fetch = [NSFetchRequest fetchRequestWithEntityName:@"Record"];
    NSEntityDescription* entity = [NSEntityDescription entityForName:@"Record"
                                              inManagedObjectContext:myManagedObjectContext];
    NSAttributeDescription* statusDesc = [entity.attributesByName objectForKey:@"status"];
    NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: @"url"]; // Does not really matter
    NSExpression *countExpression = [NSExpression expressionForFunction: @"count:"
                                                              arguments: [NSArray arrayWithObject:keyPathExpression]];
    NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
    [expressionDescription setName: @"count"];
    [expressionDescription setExpression: countExpression];
    [expressionDescription setExpressionResultType: NSInteger32AttributeType];
    [fetch setPropertiesToFetch:[NSArray arrayWithObjects:statusDesc, expressionDescription, nil]];
    [fetch setPropertiesToGroupBy:[NSArray arrayWithObject:statusDesc]];
    [fetch setResultType:NSDictionaryResultType];
    NSError* error = nil;
    NSArray *results = [myManagedObjectContext executeFetchRequest:fetch
                                                             error:&error];
    

    Found here

    0 讨论(0)
  • 2020-12-31 19:31

    You could try using an NSFetchedResultsController object to provide grouping by way of the sectionNameKeyPath construct in the initializer. Note that FRCs are mainly to be used to couple with a table view, but it's not really necessary. This way you could group your results by your sectionNameKeyPath which could be a transient attribute in your model, too.

    As a comment, I wouldn't recommend thinking of Core Data in terms of a database, which it isn't. Core Data is built to make it easier for you to persist and manage object relationships. Just because on the iOS it runs on top of SQLite doesn't make it a database replacement.

    Reference: NSFRC Reference

    0 讨论(0)
提交回复
热议问题