帮助核心数据查询

时间:2011-01-20 06:52:08

标签: iphone core-data

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

  1. 我有一个Expense对象,它有一个expenseAmount字段。
  2. 费用可以链接到ExpenseCategory对象。
  3. ExpenseCategory可能只定义费用的类别(例如食品),或者它可能具有单位费率(例如里程)。如果它只是名称,费用值是Expense对象中的expenseAmount,否则它是ExpenseCategory中的expenseAmount * unitRate。
  4. 由于费用到类别链接是可选的,最终费用将基于类别的存在/不存在以及单位费率。
  5. 因此,计算总费用的SQL查询将是:

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

    如何在CoreData中完成?

1 个答案:

答案 0 :(得分:2)

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

E.g。

- (NSDecimalNumber *) calculatedExpenseAmount {

  NSDecimalNumber *actualAmount = self.expenseAmount;

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

  return actualAmount;
}

我正在添加我以前的答案。

如果您想避免引入每个托管对象,可以使用NSDictionary-result查询来提取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。仪器将是你测量它的朋友。