2013-07-11 139 views
5

假设我有2个实体,一个Person和一个TransactionNSExpression尊重子查询NSPredicate

Person有一个一对多的关系与TransactionTransaction实体有amountdate。我的目标是建立一个基于PersonNSFetchRequest,但我只想知道在某些日期和交易金额的SUM之间有交易的人。

我的代码如下所示:

NSExpression *amountKeyPath = [NSExpression expressionForKeyPath:@"transactions.amount"]; 
NSExpression *sumAmountExpression = [NSExpression expressionForFunction:@"sum:" arguments:@[amountKeyPath]]; 

// Create the expression description for that expression. 
NSExpressionDescription *description = [[NSExpressionDescription alloc] init]; 
[description setName:@"sum"]; 
[description setExpression:sumAmountExpression]; 
[description setExpressionResultType:NSDecimalAttributeType]; 

// Create the sum amount fetch request, 
self.sumAmountFetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; 
self.sumAmountFetchRequest.resultType = NSDictionaryResultType; 
self.sumAmountFetchRequest.predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(transactions, $t, $t.date >= %@ AND $t.date <= %@)[email protected] > 0", self.startDate, self.endDate]; 
self.sumAmountFetchRequest.propertiesToFetch = @[@"name", description]; 

一切似乎都不错,但...当我看着SQL查询生成的,它看起来像:

SELECT t0.ZPERSONID, t0.ZNAME, 
    (SELECT TOTAL(t2.ZAMOUNT) FROM ZTRANSACTION t2 WHERE (t0.Z_PK = t2.ZPERSON)) 
FROM ZPERSON t0 
WHERE (SELECT COUNT(t1.Z_PK) FROM ZTRANSACTION t1 WHERE (t0.Z_PK = t1.ZPERSON AND ((t1.ZDATE >= ? AND t1.ZDATE <= ?)))) > ? 

因此,它似乎是NSExpression声明,并不尊重创建的fetchRequest的NSPredicate

是否有可能使表达式也尊重附加到fetchRequest的谓词?或者因为NSExpression自成一体,我应该附加另一个谓词呢?

+0

SQLite的声明对我来说很好的SQL。谓词转换为最后一个“WHERE”并且适用于整个语句。你有预期的结果吗? –

+0

不,我得到了属于那个人的交易金额(不限于时间范围 - WHERE子句) – Rpranata

+0

好的,现在我明白你的意思了,我上面的评论是错误的。 –

回答

5

我没有什么可以支持我自己的答案,但经过几个小时挣扎之后。我认为它不是NSExpression不尊重fetchRequest的NSPredicate,但更多的是fetchRequest的谓词是子查询。

SELECT t0.ZPERSONID, t0.ZNAME, 
    (SELECT TOTAL(t2.ZAMOUNT) FROM ZTRANSACTION t2 WHERE (t0.Z_PK = t2.ZPERSON)) 
FROM ZPERSON t0 
WHERE 
    (SELECT COUNT(t1.Z_PK) FROM ZTRANSACTION t1 WHERE (t0.Z_PK = t1.ZPERSON AND ((t1.ZDATE >= ? AND t1.ZDATE <= ?)))) > ? 

因此,谓词中的子查询并没有真正转化为我想要的WHERE子句。我想如果它是创建一个JOIN而不是,那会工作。

我的解决方案最后是以另一种方式工作。如果我创建了取自Transaction的fetchRequest,那就完美了。

NSExpression *amountKeyPath = [NSExpression expressionForKeyPath:@"amount"]; 
NSExpression *sumAmountExpression = [NSExpression expressionForFunction:@"sum:" arguments:@[amountKeyPath]]; 

// Create the expression description for that expression. 
NSExpressionDescription *description = [[NSExpressionDescription alloc] init]; 
[description setName:@"sum"]; 
[description setExpression:sumAmountExpression]; 
[description setExpressionResultType:NSDecimalAttributeType]; 

// Create the sum amount fetch request, 
self.sumAmountFetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Transaction"]; 
self.sumAmountFetchRequest.resultType = NSDictionaryResultType; 
self.sumAmountFetchRequest.predicate = [NSPredicate predicateWithFormat:@"date >= %@ AND date <= %@", self.startDate, self.endDate]; 
self.sumAmountFetchRequest.propertiesToFetch = @[@"person.name", description]; 
self.sumAmountFetchRequest.propertiesToGroupBy = @[@"person.name"]; 

这很完美。必须按照"person.name"进行分组,以便按需要使用sum:

产生将

SELECT t1.ZPERSONID, total(t0.ZAMOUNT) 
FROM ZTRANSACTION t0 
     LEFT OUTER JOIN ZPERSON t1 ON t0.ZPERSON = t1.Z_PK 
WHERE (t0.ZDATE >= ? AND t0.ZDATE <= ?) GROUP BY t1.ZPERSONID 

干杯,