Я уверен, что нет никакого способа заставить CD выполнять произвольный SQL. Если вы действительно настойчивы, попробуйте перейти прямо в SQLite. Он поддерживает все то, что вы хотите сделать.

способы написать некоторые базовые запросы в CoreData, и в документации нет примеров. Следующий мой запрос:

У меня есть объект Expense, и у него есть поле CostAmount.Расход может быть связан с объектом ExpenseCategory.ExpenseCategory может просто определять категорию для расходов (например, для продуктов питания) или может иметь единичную ставку (например, для пробега). Если это просто имя, то значение расхода - это costAmount в объекте Expense, в противном случае это - CostAmount * unitRate в ExpenseCategory.Поскольку ссылка «Расход на категорию» является необязательной, окончательные расходы будут основаны на наличии / отсутствии категории и удельной стоимости.

Таким образом, SQL-запрос для расчета общих затрат будет:

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

Как это можно сделать в CoreData?

 Nikolay Spassov24 янв. 2014 г., 21:40
Спасибо за этот вопрос. У меня похожая проблема, и NSExpression не работал для меня - я работаю с двойными и временными метками, и по какой-то причине функция split: by: дает странные результаты. Мне любопытно ваше окончательное решение, так как мне также нужно включить в мои расчеты более одной записи.

Ответы на вопрос(1)

Решение Вопроса

вашем классе расходов, который дает вам правильно рассчитанную сумму.

Например.

- (NSDecimalNumber *) calculatedExpenseAmount {

  NSDecimalNumber *actualAmount = self.expenseAmount;

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

  return actualAmount;
}

Я добавляю к моему предыдущему ответу.

Если вы хотите избежать добавления в каждый управляемый объект, вы можете использовать запрос NSDictionary-result, чтобы просто извлечь значения costAmount и costCategory.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 записей о расходах, этот выбор и расчет могут занять менее 1 МБ ОЗУ. Инструменты будут вашим другом в измерении этого.

 Bill Garrison21 янв. 2011 г., 03:53
Я уверен, что нет никакого способа заставить CD выполнять произвольный SQL. Если вы действительно настойчивы, попробуйте перейти прямо в SQLite. Он поддерживает все то, что вы хотите сделать.
 siasl20 янв. 2011 г., 10:47
Это будет работать за один счет. Я пытаюсь сопоставить все расходы в БД, не читая их все в памяти.
 siasl20 янв. 2011 г., 22:40
Спасибо за помощь. Я попытался использовать умножение: by: из класса NSExpression, чтобы сделать это вычисление в самом sqlite. Симулятор выдал исключение RT, и я считаю, что он пока недоступен на iPhone. Здесь я не понимаю, почему CoreData не поддерживает такую ​​простую вещь. Да, я знаю, что CD думает с точки зрения графов объектов, в конце концов, это все о данных.

Ваш ответ на вопрос