【问题标题】:NSPredicate SUBQUERY aggregatesNSPredicate SUBQUERY 聚合
【发布时间】:2015-12-28 22:11:42
【问题描述】:

在我看到的所有SUBQUERY 示例中,总是使用@count,例如,

SUBQUERY(employees, $e, $e.lastName == "Smith").@count > 0

所以我有三个非常相关的问题,最好作为一个 StackOverflow 问题:

  1. 如果没有@countSUBQUERY 有什么用吗?如果是这样,我还没有找到。
  2. 可以将任何其他聚合与SUBQUERY 一起使用吗?如果是这样,我无法让他们工作。 (见下文。)
  3. SUBQUERY 究竟返回了什么?合乎逻辑的事情似乎是第一个参数类型的过滤集合。 (我在这里说的是概念性的。显然 SQL 会有所不同,因为 SQL 调试非常清楚地表明了这一点。)

这给出了一个例外,就像我尝试过的除 @count 之外的所有其他聚合一样,这似乎表明无法使用其他聚合:

SUBQUERY(employees, $e, $e.lastName == "Smith").@avg.salary > 75000

(让我们暂时搁置这是否是表达这种事情的最佳方式。问题是关于SUBQUERY不是关于如何最好地制定查询。)

Mundi 有用地指出SUBQUERY 的另一个用途是嵌套子查询。是的,我知道它们并使用过它们,但这个问题实际上是关于SUBQUERY结果。如果我们将SUBQUERY 视为一个函数,那么除了@count 之外,它的结果是什么以及它可以以什么方式使用?

更新

感谢 Mundi 的研究,似乎 @avg 之类的聚合实际上可以与 SUBQUERY 一起使用,尤其是与 filteredArrayUsingPredicate: 之类的内存过滤器一起使用时,但在底层数据存储为 @ 时不适用于 Core Data 987654338@.

【问题讨论】:

    标签: core-data nspredicate


    【解决方案1】:
    1. 是的,想想嵌套子查询。请参阅 Dave DeLong 的 answer,它用非常简单的术语解释了子查询。
    2. 您的@avg 不起作用的原因未知,因为它实际上应该适用于具有聚合函数所需的适当属性的任何集合。
    3. 参见 1.:SUBQUERY 返回一个集合。

    这是证明子查询按预期工作的实验记录。

    import UIKit
    import CoreData
    
    class Department: NSManagedObject {
        var name = "Department"
        var employees = Set<Person>()
    
        convenience init(name: String) {
            self.init()
            self.name = name
        }
    }
    
    class Person: NSManagedObject {
        var name: String = "Smith"
        var salary: NSNumber = 0
    
        convenience init(name: String, salary: NSNumber) {
            self.init()
            self.name = name
            self.salary = salary
        }
    }
    
    let department = Department()
    department.employees = Set ([
     Person(name: "Smith", salary: NSNumber(double: 30000)),
     Person(name: "Smith", salary: NSNumber(double: 60000)) ])
    
    
    let predicate = NSPredicate(format: "SUBQUERY(employees, $e, $e.name = %@).@avg.salary > 44000", "Smith")
    
    let depts = [department, Department()]
    let filtered = (depts as NSArray).filteredArrayUsingPredicate(predicate)
    

    上面只返回一个部门和两名员工。如果我在谓词中替换 45000,结果将不返回任何内容。

    【讨论】:

    • 如果@count 聚合可以应用到SUBQUERY,它不是已经是一个集合了吗?为什么我可以说employees.@countemployees.@avg.salarySUBQUERY().@count 而不能说SUBQUERY().@avg.salary
    • 回答您的问题:显然,avg 聚合函数需要来自被查询集合的更多信息,而不仅仅是 count
    • 所以你是说SUBQUERY 表达式的结果是一个计数,而不是一个过滤的集合?这似乎没有多大意义。如果这是真的,我们会说SUBQUERY(...) &gt; 0 而不是SUBQUERY(...).@count &gt; 0
    • 我想你和我一定对SUBQUERY有不同的心智模型。对我来说,它看起来很像 Haskell 或 Python 中的列表推导,尽管语法更简单。因此,它应该返回过滤实体的集合。如果我可以说employees.@avg.salary,我应该可以说SUBQUERY(employees, ...).@avg.salary,但我不能。我怀疑这只是将谓词翻译成底层语言(例如 SQL 或 XPath)的技术限制。
    • 我收回我说的话。经过一些实验,我得出结论,您最初的假设是正确的。您得到的错误一定是由于其他原因。我修改了答案并展示了第 1 点和第 2 点(我猜是第 3 点)。
    猜你喜欢
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多