Query too complex for me - some help required
ahartman opened this issue · comments
I tried a new query based on examples from you:
func getPatientTimeline() -> [PatientTimelineInfo] {
var patientTimelineInfo = [PatientTimelineInfo]()
do {
patientTimelineInfo = try db.read { db in
let request = Patient
.select(
Column("id"),
Column("patientName")
)
.order(Column("patientName"))
.annotated(with:
Patient.visits.min(Column("visitCreated")),
Patient.visits.max(Column("visitDate")))
return try PatientTimelineInfo
.fetchAll(db, request)
}
} catch {
fatalError("Unresolved error \(error)")
}
return patientTimelineInfo
}
However this applies to more visits than required, I need to filter the visits for which I calculate the minimum and maximum Dates as in another query below:
func getPatientForCSV(dates: PeriodStartEnd) -> [PatientInfo] {
var patientInfo = [PatientInfo]()
do {
patientInfo = try db.read { db in
let filteredVisits = Patient.visits
.filter(Column("visitDate") >= dates.start)
.filter(Column("visitDate") <= dates.end)
.filter(["Marieke", "Marieke nieuwe"].contains(Column("visitCalendar")))
return try Patient
.including(all: filteredVisits)
.having(filteredVisits.isEmpty == false)
.asRequest(of: PatientInfo.self)
.fetchAll(db)
}
} catch {
fatalError("Unresolved error \(error)")
}
return patientInfo
}
How can I get the effect of the line - .filter(["Marieke", "Marieke nieuwe"].contains(Column("visitCalendar"))) - in query 2 applied to query 1?
Still happy with GRDB.
Kind regards, André Hartman, Belgique
Environment
**GRDB flavor(s): GRDB
**GRDB version: master
**Installation method: package
**Xcode version: 15.2
**Swift version: 5
**Platform(s) running GRDB: Mac Catalyst
**macOS version running Xcode: Sonoma 14.3.1
Hi @ahartman,
I'm far away from any computer, so I'm not able to verify the validity of my answer.
Did you try to replace Patient.visits
, in query 1, with the local variable filteredVisits
defined as below?
let filteredVisits = Patient.visits
.filter(["Marieke", "Marieke nieuwe"].contains(Column("visitCalendar")))
This is the same technique as in query 2: you replace the association of all visits with its filtered version.
Dear Gwendal,
I found the solution - finally - myself.
As I filter the patient visits for their Calendar, I may end up with patients without any visits in the result set.
They, of course do not have a filteredVisits.min(Column("visitCreated")) nor a filteredVisits.max(Column("visitDate")); the result is the GRDB error.
I needed to add the line ".having(filteredVisits.isEmpty == false)" and all was well.
I was reminded again that SQL is a subtle science.
Regards, André Hartman
I'm back from vacations, and you have solved your issue, @ahartman 👍🙂
The Assertion failed: unexpected NULL value
error is interesting, because it is the sign of an actual GRDB bug (yeah, a real one). I won't bother you with asking for a way to reproduce the error, but if you have some spare time to put on this, this would be appreciated.
Until then, or until your next question, happy GRDB!
I do not think this is a GRDB issue; my error was to query a potential NULL result into a non-optional value.
It is a GRDB bug, because assertions like this are never supposed to be triggered.
This is a repeatable error, so it is easy to reproduce for you.
When I have the code and data that reproduces (something that compiles and runs on data that triggers the bug), yes I guess it starts to be easy ;-) Right now there are too many uninformed guesses to do.