子查询中的 NSPredicate

Posted

技术标签:

【中文标题】子查询中的 NSPredicate【英文标题】:NSPredicate Inside a SUBQUERY 【发布时间】:2016-04-19 13:49:37 【问题描述】:

我正在尝试为 NSPredicate 编写一个 SUBQUERY。我的问题是我手头没有 SUBQUERY 的谓词部分的查询。有没有办法在 SUBQUERY 中嵌套一个 NSPredicate?

例如这是我尝试过的:

let ordersPredicate = NSPredicate()//some predicate passed in
//how do I use the ordersPredicate inside the subquery??
let subQueryPredicate = NSPredicate(format: "SUBQUERY(orders, $x,'%@').@count > 0", ordersPredicate.predicateFormat)

更新:我现在不得不通过执行第一个谓词并执行 ANY IN 查询来做一个肮脏的解决方法。它的蹩脚:(因为我正在其他地方执行ordersPredicate以及稍后在管道中..

let fetchRequest = NSFetchRequest()//blah
fetchRequest.predicate = orderPredicate
let orders = //execute fetch
let subQueryPredicate = NSPredicate(format: "SUBQUERY(orders, $x, ANY $x in %@).@count > 0", orders)

【问题讨论】:

您能否发布您的订单类/定义并解释您想要实现的目标? 在您不需要子查询的解决方法中,ANY orders in %@ 就可以了。为什么将returnObjectsAsFaults 设置为false? 如果你想在子查询中使用谓词,谓词应该是$x.orderNumber = 10,with$x。可以转换谓词,但重新设计管道可能更容易。 感谢您的建议。 @vikingosegundo 我正在尝试查询与订单有 toMany 关系的分支实体。基本上我想查询订单谓词中的任何分支。 @Willeke 我复制了该代码,但在上下文中设置 returnObjectsAsFalse 没有意义。感谢您的建议,我正在考虑重新设计一些东西 【参考方案1】:

感谢@Willeke 的一些建议,我能够想出一个解决方案。

public extension NSPredicate
    public func stringForSubQuery(prefix:String) -> String
        var predicateString = ""
        if let predicate = self as? NSCompoundPredicate
            for (index, subPredicate) in predicate.subpredicates.enumerate()

                if let subPredicate = subPredicate as? NSComparisonPredicate
                    predicateString = "\(predicateString) \(prefix)\(subPredicate.predicateFormat)"
                
                else if let subPredicate = subPredicate as? NSCompoundPredicate
                    predicateString = "\(predicateString) (\(subPredicate.stringForSubQuery(prefix)))"
                
                //if its not the last predicate then append the operator string
                if index < predicate.subpredicates.count - 1 
                    predicateString = "\(predicateString) \(getPredicateOperatorString(predicate.compoundPredicateType))"
                
            
        
        return predicateString
    
    private func getPredicateOperatorString(predicateType: NSCompoundPredicateType) -> String
        switch(predicateType)
        case .NotPredicateType: return "!"
        case .AndPredicateType: return "&&"
        case .OrPredicateType: return "||"
        
    

这是用法

let ordersPredicate = NSPredicate()//some predicate passed in
let ordersPredicateFormat = orderPredicate.stringForSubQuery("$x.")
let subQueryPredicate = NSPredicate(format: "SUBQUERY(orders, $x, \(ordersPredicateFormat)).@count > 0")

【讨论】:

【参考方案2】:

对于将来遇到此问题的任何人,您无需自己构建谓词字符串,只需在子查询字符串中直接使用predicateFormat。它已经被正确转义了,所以使用字符串插值。

let ordersPredicate = NSPredicate()
// Add it to the query with string interpolation
let subQueryPredicate = NSPredicate(format: "SUBQUERY(orders, $x, \(ordersPredicate.predicateFormat)).@count > 0")

如果你尝试将它作为参数传递,它会再次尝试转义字符串,这可能不起作用。

// Don't do this!
let subQueryPredicate = NSPredicate(format: "SUBQUERY(orders, $x, %@).@count > 0", ordersPredicate.predicateFormat)

【讨论】:

以上是关于子查询中的 NSPredicate的主要内容,如果未能解决你的问题,请参考以下文章

MySQL基础语法之子链接查询和特殊查询(union 和 limit)

MySQL的子查询中FROM和EXISTS子句的使用教程

06-mysql基础-mysql中的DQL-子查询

[转]HQL中的子查询

子查询中的子查询在配置单元中不起作用

子查询中的 sqlalchemy 表冒泡到外部查询中