2011-01-20 36 views
5

Tôi đang tìm cách viết một số truy vấn cơ bản trong CoreData và không có ví dụ trong tài liệu. Sau đây là truy vấn của tôi:Trợ giúp với Truy vấn CoreData

  1. Tôi có đối tượng Chi phí và có trường costAmount.
  2. Chi phí có thể được liên kết với đối tượng ExpenseCategory.
  3. ExpenseCategory chỉ có thể xác định danh mục cho chi phí (ví dụ: Thực phẩm) hoặc có thể có một đơn vị (ví dụ: Mileage). Nếu nó chỉ là tên, giá trị chi phí là costAmount trong đối tượng Expense khác là costAmount * unitRate trong ExpenseCategory.
  4. Vì liên kết Chi phí đến Danh mục là tùy chọn, chi phí cuối cùng sẽ dựa trên sự hiện diện/vắng mặt của Danh mục và tỷ lệ đơn vị.

Vì vậy, một truy vấn SQL để tính toán tổng chi phí sẽ là:

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

Làm thế nào điều này có thể được thực hiện trong CoreData?

+0

Cảm ơn bạn đã đặt câu hỏi này. Tôi có một vấn đề tương tự và NSExpression đã không làm việc cho tôi - Tôi đang làm việc với đôi và dấu thời gian và vì một lý do nào đó phân chia: bởi: chức năng tạo ra kết quả lạ. Tôi tò mò về giải pháp cuối cùng của bạn vì tôi cũng cần bao gồm nhiều hơn một bản ghi duy nhất trong tính toán của mình. –

Trả lời

2

Một giải pháp đơn giản hơn có thể là triển khai phương pháp khác trên lớp Chi phí cung cấp cho bạn số tiền được tính thích hợp.

Ví dụ:

- (NSDecimalNumber *) calculatedExpenseAmount { 

    NSDecimalNumber *actualAmount = self.expenseAmount; 

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

    return actualAmount; 
} 

tôi thêm vào câu trả lời trước đây của tôi.

Nếu bạn muốn tránh kéo vào mọi đối tượng được quản lý, bạn có thể sử dụng truy vấn kết quả NSDictionary để chỉ cần rút ra các giá trị costAmount và 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]; 
} 

Nếu bạn có 10.000 mục nhập chi phí, quá trình tìm nạp và tính toán này có thể nhỏ hơn 1MB RAM. Dụng cụ sẽ là bạn của bạn trong việc đo lường điều đó.

+0

Điều này sẽ làm việc cho một chi phí duy nhất. Tôi đang cố gắng để đối chiếu cho tất cả các chi phí trong DB mà không đọc tất cả chúng trong bộ nhớ. – siasl

+0

Cảm ơn sự giúp đỡ. Tôi đã thử bằng cách sử dụng nhân: bởi: từ lớp NSExpression để làm tính toán này trong sqlite chính nó. Simulator đã ném một ngoại lệ RT và tôi nghĩ rằng nó không có sẵn trên iPhone được nêu ra. Những gì tôi không hiểu ở đây là tại sao CoreData không có hỗ trợ cho một điều đơn giản như vậy. Vâng, tôi biết CD nghĩ về đồ thị đối tượng, cuối cùng nó là tất cả về dữ liệu. – siasl

+0

Tôi chắc chắn không có cách nào để làm cho CD thực thi SQL tùy ý. Nếu bạn thực sự liên tục, bạn có thể thử truy cập trực tiếp vào SQLite. Nó hỗ trợ tất cả những thứ bạn muốn làm. –

Các vấn đề liên quan