Group values by year, month, day #77
-
| Hi there, I'm trying to migrate my app to SharingGRDB/StructuredQueries. So far so good. What I'm trying to achieve is to group values by part of a timestamp. I have this table in my database: @Table
struct Weight: Identifiable, Equatable, CustomDebugStringConvertible, Hashable, Codable {
    let id: Int
    var timestamp: Date
    var weightInKilograms: Double
    init(id: Int, timestamp: Date, weight: Measurement<UnitMass>) {
        self.id = id
        self.timestamp = timestamp
        self.weight = weight
    }
    ....
}as you can see the timestamp contains a date along with a timestamp. Now what I would like to do is to create an overview of all weights per day: import Foundation
import SharingGRDB
import SwiftUI
@Selection
struct GroupedWeights: Equatable, Hashable {
    var date: Date
    @Column(as: [Weight].JSONRepresentation.self)
    var weights: [Weight]
}
@Observable
class WeightListModel {
    @ObservationIgnored
    @Dependency(\.defaultDatabase) var database
    @ObservationIgnored
    @FetchAll
    var groupedWeights: [GroupedWeights]
    var startDate: Date
    var endDate: Date
    init(startDate: Date, endDate: Date) {
        self.startDate = startDate
        self.endDate = endDate
        self._groupedWeights = FetchAll(
            Weight
                .where { $0.timestamp.between(#bind(startDate), and: #bind(endDate)) }
                .group { $0.timestamp }
                .order { $0.timestamp.desc() }
                .select { GroupedWeights.Columns(date: $0.timestamp, weights: $0.jsonGroupArray()) }
        )
    }
}the code above works, but the  select * from weight
group by date(timestamp)
order by timestampand later I will need: select * from weight
group by strftime('%Y%m', timestamp)
order by timestampbut I'm struggling to implement any of the above. Is it possible to implement anything like this with StructuredQueries? kind regards, Tim | 
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 4 replies
-
| @thinkpractice StructuredQueries comes with a lot of helpers out of the box, but it doesn't currently implement the date functions (we are open to PRs here, but SQLite date functions are in particular quite nuanced/flexible with their input/output). Instead you can use the  .group { #sql("date(\($0.timestamp))" }
// or
.group { #sql("strftime('%Y%m', \($0.timestamp))") }The  | 
Beta Was this translation helpful? Give feedback.
-
| @stephencelis the  I found out that the same code would not work in the select clause though: .select {
                    GroupedWeights.Columns(date: #sql("date(\($0.timestamp))" ?? $0.timestamp, weights: $0.jsonGroupArray())
 }It throws an error when mapping back to the date in the  | 
Beta Was this translation helpful? Give feedback.
-
| @stephencelis the  | 
Beta Was this translation helpful? Give feedback.

@thinkpractice Ah, that's true, currently you must specify the type if it can't be inferred, and at the moment it can't here. So you'd need to do:
We can look into if it's possible to weaken this requirement, though!
If you are able to define them in reasonable ways we'd be happy to consider them for inclusion in the library, but they are complicated in how they accept various inputs (dates, text, integers, doubles) and how they can fail.