2011-11-15 9 views
2

子エンティティの属性の平均値を取得しようとしていますが、選択されたレコードセットのみを含めようとしています。いくつかのオブジェクトをフィルタリングしながら平均値を取得する最も効率的な方法

私のCore DataモデルにはInvoiceとInvoiceDetailという2つのエンティティがあります。

Invoice:<br> 
    invoiceNum - attribute<br> 
    invoiceDate - attribute<br> 
    invoiceDetails - one-to-many relationship to InvoiceDetail 

InvoiceDetail:<br> 
    itemAmount - attribute<br> 
    itemType - attribute<br> 
    invoice - one-to-one relationship to Invoice<br> 

私はちょうど全体の請求書のitemAmountの平均値を取得したい場合は、私は以下を使用します(請求書がNSManagedObjectである):

float avgAmount = [[invoice valueForKeyPath:@"[email protected]"] floatValue]; 

しかし、私だけにしようとしていますitemType = 1のオブジェクトの平均値を取得します。私はinvoiceDetailアイテムをループして手動で行うことができますが、パフォーマンス上の問題が発生することがわかります。私はこれをやり遂げる最善の方法は何か分かりません。

ありがとうございました。

答えて

8

次のようにあなたは、表現が含まれているフェッチ要求でそれを行うことができます。

- (NSDictionary *)myFetchResults 
{ 
    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    request.entity = [NSEntityDescription entityForName:@"InvoiceDetail" inManagedObjectContext:myContext]; 
    request.predicate = [NSPredicate predicateWithFormat:@"itemType = %@", [NSNumber numberWithInt:1]]; 

    request.resultType = NSDictionaryResultType; 

    NSExpressionDescription *aveExDescr = [[NSExpressionDescription alloc] init]; 
    [aveExDescr setName:@"myAverage"]; 
    [aveExDescr setExpression:[NSExpression expressionForFunction:@"average:" 
                 arguments:[NSArray arrayWithObject: 
                    [NSExpression expressionForKeyPath:@"itemAmount"]]]]; 
    [aveExDescr setExpressionResultType:NSFloatAttributeType]; 

    request.propertiesToFetch = [NSArray arrayWithObject:aveExDescr]; 

    NSError *err = nil; 
    NSArray *results = [self.moContext executeFetchRequest:request error:&err]; 
    [request release]; 
    [err release]; 

    return results; 
} 

フェッチは、次のようにアクセスすることができ、辞書を返します。

NSArray *results = [self myFetchResults]; 
NSDictionary *resultsDictionary = [results lastObject]; 
NSNumber *average = [resultsDictionary objectForKey:@"myAverage"]; 

に留意されたいです。このコードはテストされていません。 NSDecimalNumbersを使用している場合は、float型の代わりにNSDecimalAttributeTypeを使用することもできます。

+0

ありがとう、これは本当に役に立ちます!私は、私が含めるのに苦労している別のフィルタを求められました。 Invoiceエンティティには、整数値を持つinvoiceStatusという別の属性が含まれています。 invoiceStatusが1のInvoiceオブジェクトをフィルタリングしたい場合は、NSPredicateを複数のエンティティで使用できますか?私はFetchRequestエンティティを "Invoice"に変更しようとしていましたが、@ "invoiceStatus ==%@ AND invoiceDetails.itemType ==%@"という述語を使用していましたが、それは機能しません。 – user684360

+0

はい、複数のエンティティおよび複合述語で作業できます。対多関係で不適切に操作しているため、述部が機能していません。請求書には多くのInvoiceDetailsがあり、述語には、要求された値を持つitemTypeを持つものが少なくとも1つあるかどうかを尋ねる必要があります。あなたはサブクエリでそれを行うことができます。 –

+0

これらの質問([A](http://stackoverflow.com/questions/2029962/using-nspredicate-with-core-data-for-deep-relationships)&[B](http://stackoverflow.com/questions)/2006927/whats-better-way-to-build-nspredicate-with-many-deep-relationships))には、サブクエリを設定する方法の例がいくつかあります。 –

関連する問題