NSExpression 尊重子查询 NSPredicate
Posted
技术标签:
【中文标题】NSExpression 尊重子查询 NSPredicate【英文标题】:NSExpression respect a subquery NSPredicate 【发布时间】:2013-07-11 11:00:05 【问题描述】:假设我有 2 个实体,一个 Person
和一个 Transaction
。
Person
与Transaction
和Transaction
具有一对多关系,实体具有amount
和date
。我的目标是在Person
的基础上获得NSFetchRequest
,但我只想知道在特定日期之间进行交易的人以及交易金额的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
是独立存在的,我应该给它附加一个谓词?
【问题讨论】:
SQLite 语句对我来说看起来不错。谓词转换为最后一个“WHERE”并应用于整个语句。你得到预期的结果了吗? 不,我得到了属于那个人的交易量(不限于时间范围 -- WHERE 子句) 好的,现在我明白你的意思了,我上面的评论是错误的。 【参考方案1】:我没有什么可以支持我自己的答案,但是在为此苦苦挣扎了几个小时之后。我认为这不是 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
干杯,
【讨论】:
以上是关于NSExpression 尊重子查询 NSPredicate的主要内容,如果未能解决你的问题,请参考以下文章