2011-01-20 93 views
5

我正在寻找方法在CoreData中编写一些基本查询,并且文档中没有示例。以下是我的查询:有关CoreData查询的帮助

  1. 我有一个费用对象,它有一个expenseAmount字段。
  2. 费用可以链接到ExpenseCategory对象。
  3. ExpenseCategory可能只是定义费用的类别(例如Food),或者它可能有单位费率(例如,里程)。如果它只是名称,则费用值为费用对象中的费用总额,否则为费用类别中的费用总额*单位费率。
  4. 由于费用到分类链接是可选的,因此最终费用将基于类别和单位费率的存在/不存在。

因此,一个SQL查询来计算总的费用是:

select 
    TOTAL(e.amount * IFNULL(c.rate, 1)) 
from EXPENSE e 
LEFT OUTER join CATEGORY c on 
    e.category = c.id 

怎么能在这个被CoreData做?

+0

谢谢你的这个问题。我有一个类似的问题,NSExpression不适合我 - 我正在使用双打和时间戳,由于某种原因,divide:by:函数会产生奇怪的结果。我很好奇你的最终解决方案,因为我还需要在计算中包含多条记录。 – 2014-01-24 20:40:35

回答

2

一个更简单的解决方案可能是在您的费用类上实现另一种方法,该方法可为您提供适当的计算量。

E.g.

- (NSDecimalNumber *) calculatedExpenseAmount { 

    NSDecimalNumber *actualAmount = self.expenseAmount; 

    // Pseudo-code begins 
    if (self.expenseCategory != nil) { 
    actualAmount = self.expenseAmount * self.expenseCategory.unitRate; 
    } 

    return actualAmount; 
} 

我添加到我以前的答案。

如果您希望避免牵扯每个托管对象,那么可以使用NSDictionary结果查询来提取expenseAmount和expenseCategory.unitRate值。

- (NSDecimalNumber *) totalExpenses 
{ 
    // Fetch all of the expense amounts and unit rate of any related category. 

    NSFetchRequest *request = ...; 
    [request setManagedObjectContext:<...>]; 
    [request setEntity:<ExpenseAccountDescription>]; 
    [request setResultType:NSDictionaryResultType]; 
    NSArray *props = [NSArray arrayWithObjects:@"expenseAmount", @"category.unitRate", nil]; 
    [request setPropertiesToFetch:props]; 

    NSArray *amounts = [request executeRequest:...]; 
    // amounts is an array of dictionaries, each hold the desired property values. 

    // Loop and sum the individual amounts 

    NSDecimal *total = [[NSDecimalNumber zero] decimalNumber]; 
    NSAutoreleasePool *pool = nil; // contain the mess 

    NSCalculationError err = NSCalculationNoError; 

    for (NSDictionary *result in amounts) 
    { 
     pool = [NSAutoreleasePool new]; 

     NSDecimal newTotal = [[NSDecimalNumber zero] decimalNumber]; 
     NSDecimalNumber *expenseAmount = [result valueForKeyPath:@"expenseAmount"]; 
     NSDecimalNumber *unitRate = [result valueForKeyPath:@"category.unitRate"]; 

     if (unitRate != nil) { 
      // do the unit rate multiplication and accumulate the result in the total 

      NSDecimal calculated = [[NSDecimalNumber zero] decimalNumber]; 
      err = NSDecimalMultiply (&calculated, [expenseAmount decimalNumber], [unitRate decimalNumber], NSRoundBankers); 
      if (err == NSCalculationNoError) { 
       err = NSDecimalAdd (&newTotal, total, calculated, NSRoundBankers); 
      } 
     } 
     else { 
      // just accumulate the result in the total 

      err = NSDecimalAdd (&newTotal, total, [expenseAmount decimalNumber], NSRoundBankers); 
     } 

     // Keep the new total 
     NSDecimalCopy(&total, newTotal); 

     [pool drain]; 
    } 

    return [NSDecimalNumber decimalNumberWithDecimal:total]; 
} 

如果您有10000个费用条目,则此提取和计算可能会少于1MB的RAM。仪器将是你的朋友测量。

+0

这可以用于单一开支。我正在尝试整理数据库中的所有费用,而没有在内存中读取所有这些费用。 – siasl 2011-01-20 09:47:40