2011-02-03 3 views
0

Je voudrais avoir l'équivalent des données de base de la fonction SQL:compte distinct

SELECT species, sex, COUNT(*) FROM Bird GROUP BY species, sex; 

Une demande qui renvoie par cette

+---------+------+----------+ 
| species | sex | COUNT(*) | 
+---------+------+----------+ 
| Bus  | m |  2 | 
| Car  | f |  1 | 
+---------+------+----------+ 

avec les entrées suivantes:

INSERT INTO Bird VALUES ('BlueBird','Car','f'); 
INSERT INTO Bird VALUES ('RedBird','Bus','m'); 
INSERT INTO Bird VALUES ('RedBird','Bus','m'); 

J'ai répondu à la demande distincte, mais j'ai du mal à avoir le compte (*). Voici ce que j'ai:

NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Bird" inManagedObjectContext:managedObjectContext]; 
[request setEntity:entity]; 
[request setReturnsDistinctResults:YES]; 
[request setResultType:NSDictionaryResultType]; 
NSDictionary *entityProperties = [entity propertiesByName]; 

NSMutableArray *properties = [NSMutableArray arrayWithObject:[entityProperties objectForKey:@"species"]]; 
[properties addObject:[entityProperties objectForKey:@"sex"]]; 
[request setPropertiesToFetch: properties]; 

Que dois-je ajouter?

Un grand merci

Répondre

1

Le modèle de données sous-entendus par les données de l'échantillon suggère que vous auriez à chercher tous les objets, filtrer et réextrait:

NSManagedObjectContext *moc; 
NSEntityDescription *birdEntity = [NSEntityDescription entityForName:"Bird" inManagedObjectContext:moc]; 

NSFetchRequest *fetchAllBirds = [[NSFetchRequest new] autorelease]; 
[fetchAllBirds setEntity:birdEntity]; 
NSArray *allBirds = [moc executeFetchRequest:fetchAllBirds error:NULL]; 

NSArray *species = [allBirds valueForKeyPath:@"@distinctUnionOfObjects.species"]; 

NSMutableDictionary *speciesCounts = [NSMutableDictionary dictionaryWithCapacity: [species count]]; 
for (NSString *speci in species) 
{ 
    NSFetchRequest *fetchSpeci = [[NSFetchRequest new] autorelease]; 
    [fetchSpeci setEntity: birdEntity]; 
    [fetchSpeci setPredicate:[NSPredicate predicateWithFormat:@"speci == %@", speci]]; 

    int speciCount = [moc countForFetchRequest:fetchSpeci]; 
    [speciesCounts setObject:[NSNumber numberWithInt:speciCount] forKey:speci]; 
} 

Je vous suggère de remodeler les données. Vous pouvez remplacer l'attribut species par une relation avec une entité Species. CoreData n'est pas une base de données relationnelle, c'est un framework de persistance de graphe d'objet. Si vous essayez de l'utiliser comme base de données relationnelle, vous vous retrouverez dans un pétrin.

+0

Merci pour votre réponse Benoît. En fait, j'ai pensé à un tel algorithme, mais il finit par ne pas être très rapide sur des ensembles de données plus importants. Peut-être que je devrais essayer de l'affiner, mais je pensais que tout obtenir en une seule demande serait vraiment plus efficace. – lorenzo