【问题标题】:SQL to CoreData, sum of two or more multiplied attributesSQL 到 CoreData,两个或多个相乘属性的总和
【发布时间】:2011-11-13 16:58:34
【问题描述】:

如何翻译 SQL:

select sum( field1 * field2 ) from table where field3 = 8

到等效的 CoreData NSPredicate 代码,好吗?是否可以不获取所有内容并运行丑陋的 for 循环?

【问题讨论】:

  • for 循环有什么难看的? CoreData 是一个对象图,而不是数据库替代品。
  • De gustibus non est disputandum,在我看来很丑。如果您看不到上述 sql 与 for 循环的优雅之处,那就足够了。
  • 而且,获取 20,000 条记录来执行这样一个简单的操作是浪费时间和内存。

标签: sql objective-c core-data


【解决方案1】:

为什么需要在 SQL 中执行?

如果您使用的是NSManagedObject 子类,那么您可以创建一个虚拟属性来执行该计算。 (忽略命名我不知道你的域)

MyClass.h

@property (nonatomic, readonly) CGFloat sumOfField1AndField2;

MyClass.m

- (CGFloat)sumOfField1AndField2;
{
   return self.field1 * self.field2;
}

【讨论】:

  • 我猜如果是通过SQL完成,性能会更好。如果做不到,我会听从你的建议,谢谢。
  • 如果您在分析应用时确实发现了一个大问题,那么可能是时候重新评估这种方法了,但在此之前,最简单的事情往往是最好的,过早的优化几乎总是不好的。跨度>
  • 这是一个非常有效的问题(可能是例子不太容易理解)考虑这个:实体饮料与属性 dateOfDrink、countOfDrinksTaken 和 pricePerDrink 我想查询数据库的日期范围内的成本 - 我想获取总和(countOfDrinksTaken * pricePerDrink)。
  • 这需要在 SQL 中执行,因为获取所有托管对象会占用大量内存。
【解决方案2】:

您的实体应该有一个 fetched property 计算属性,该属性将这两个字段相乘。您的查询的解决方案是结合NSPredicate 和键值编码:

fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"table"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"field3 = %@", @8];
NSArray *results = [self.managedObjectContext 
       executeFetchRequest:fetchRequest error:nil]; 

NSNumber *sum = [results valueForKeyPath:@"@sum.fetchedProperty"]; 

正如您所指出的,它实际上不是一个获取的属性,而是一个计算的字段。我按照这些思路做了一个测试:

// NSManagedObjectSubclass .h
@property (nonatomic, strong) NSNumber *product;

// .m
@dynamic product;

-(NSNumber *)product { 
   return @(value1.floatValue * value2.floatValue); 
}

这很有效:

NSLog(@"Sum of products: %@", [fetchedObjects valueForKeyPath:@"@sum.product"]; 

【讨论】:

  • 抱歉很厚,但相关部分指出,获取的属性表示弱的单向关系,并且总是返回 NSArray。如何创建将两个字段相乘的提取属性?
  • 你是对的,获取的属性不是正确的术语。请参阅我修改后的答案。
  • 这是@Paul.s 已经建议的,我现在确实在这样做,但我对这个解决方案不满意,因为它需要将所有记录从数据库提取到内存。对于数千条记录来说,这几乎不是一个理想的解决方案。我正在试验 NSExpression 和 multiply:by: 但它似乎在 iOS 上不受支持 :( stackoverflow.com/questions/13879025/…
  • 并没有你想的那么糟糕。 Core Data 非常擅长减少幕后的内存占用。如果你想对所有值求和,无论如何你都会触及所有记录。 CD 将优化以不获取它不需要的字段(通过故障)。
猜你喜欢
  • 2023-03-16
  • 2012-08-23
  • 1970-01-01
  • 1970-01-01
  • 2018-03-22
  • 2018-07-17
  • 1970-01-01
  • 2023-03-14
  • 2013-12-15
相关资源
最近更新 更多