给出Calls
表:
+--------+--------+----------+
| caller | callee | duration |
+--------+--------+----------+
| A | B | 3 |
| B | C | 1 |
| C | A | 2 |
| B | A | 5 |
+--------+--------+----------+
期望的输出:
+------------+-------+
| subscriber | total |
+------------+-------+
| A | 10 |
| B | 9 |
| C | 3 |
+------------+-------+
如何设置NSFetchRequest以获得所需的输出?
答案 0 :(得分:0)
我必须以某种方式解决它(下面的代码不是我应用程序中的实际代码,而是草图)。它是一种“混合”解决方案,介于仅提取(我怀疑是可能的,CoreData缺少联合)和完整的内存之间。
class Subscriber:NSObject {
@objc dynamic var subscriber = 0
@objc dynamic var total = 0
init(dictionary: NSDictionary) {
if let s = dictionary["caller"] as? Int { subscriber = s}
if let t = dictionary["total"] as? Int { total = t }
super.init()
}
init(dictionary: NSDictionary, _:Bool) {
if let s = dictionary["callee"] as? Int { subscriber = s}
if let t = dictionary["total"] as? Int { total = t }
super.init()
}
在do ... catch:
中获取一个Subscriber对象数组let req_a = NSFetchRequest<NSDictionary>(entityName:"Call")
let durExp = NSExpression(forKeyPath: "duration")
let sumDesc = NSExpressionDescription()
sumDesc.expression = NSExpression(forFunction: "sum:", arguments: [durExp])
sumDesc.name = "total"
sumDesc.expressionResultType = .integer64AttributeType
req_a.propertiesToGroupBy = ["caller"]
req_a.propertiesToFetch = ["caller", sumDesc]
req_a.resultType = .dictionaryResultType
let req_b = NSFetchRequest<NSDictionary>(entityName:"Call")
req_b.propertiesToGroupBy = ["callee"]
req_b.propertiesToFetch = ["callee", sumDesc]
req_b.resultType = .dictionaryResultType
var subscriberResults_a = try theMOC.fetch(req_a).map { return Subscriber(dictionary: $0) }
var subscriberResults_b = try theMOC.fetch(req_b).map { return Subscriber(dictionary: $0, true) }
/// Add values from duplicates
subscriberResults_a = subscriberResults_a?.map { a -> Subscriber in
guard let b = subscriberResults_b?.first(where: { $0.subscriber == a.subscriber }) else { return a }
a.total += b.total
return a
}
/// Filter out duplicates
subscriberResults_b = subscriberResults_b?.filter({ b -> Bool in
if let found = subscriberResults_a?.contains (where: { $0.subscriber == b.subscriber }) { return !found }
return true
})
subscriberArray = subscriberResults_a! + subscriberResults_b!
仍在寻找更好的解决方案。