NSExpression尊重子查询NSPredicate

Rpr*_*ata 5 cocoa-touch core-data nspredicate ios nsexpression

假设我有2个实体,a Person和a Transaction.

Person有一个一对多的关系TransactionTransaction实体有amountdate.我的目标是建立一个NSFetchRequest基于Person,但我只想知道在某些日期和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 <= %@).@count > 0", self.startDate, self.endDate];
self.sumAmountFetchRequest.propertiesToFetch = @[@"name", description];
Run Code Online (Sandbox Code Playgroud)

一切似乎都很好但是......当我查看生成的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 <= ?))) ) > ? 
Run Code Online (Sandbox Code Playgroud)

所以,似乎NSExpression声明,不尊重NSPredicatefetchRequest创建.

是否可以使表达式也遵循附加到fetchRequest的谓词?或者从NSExpression单独看,我应该附加另一个谓词?

Rpr*_*ata 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 <= ?))) ) > ? 
Run Code Online (Sandbox Code Playgroud)

因此,谓词中的子查询并没有真正转换为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"];
Run Code Online (Sandbox Code Playgroud)

这非常有效.它必须按其分组"person.name"才能使用sum:所需的.

生成的SQL将是

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 
Run Code Online (Sandbox Code Playgroud)

干杯,