假设我有2个实体,Person
和Transaction
。
Person
与Transaction
和Transaction
实体之间存在多对多关系amount
和date
。我的目标是根据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];
一切似乎都很好但是...当我查看生成的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 :(得分: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:
。
生成的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
干杯,