我很迷失。我尝试使用这个实体来聚合数据
@Entity
@Table(
name = "page_view",
indexes = [
Index(name = "idx_page_view_site_date", columnList = "site_id,viewed_at"),
Index(name = "idx_page_view_session", columnList = "session_id"),
Index(name = "idx_page_view_url", columnList = "url")
]
)
data class PageView(
@Id @GeneratedValue(strategy = GenerationType.UUID)
val id: String? = null,
val sessionId: String,
val url: String,
val viewedAt: LocalDateTime,
)
存储库
@Query(
"""
SELECT new com.eventuallycoding.blogiq.repository.DailyViewStats(
CAST(pv.viewedAt as date),
COUNT(pv.id) ,
COUNT(DISTINCT pv.sessionId)
)
FROM PageView pv
WHERE pv.site = :site
AND (:url IS NULL OR pv.url = :url)
AND pv.viewedAt BETWEEN :startDate AND :endDate
GROUP BY CAST(pv.viewedAt as date)
ORDER BY CAST(pv.viewedAt as date) ASC
"""
)
fun findDailyViewStatsBySiteAndInterval(
@Param("site") site: Site,
@Param("startDate") startDate: LocalDateTime,
@Param("endDate") endDate: LocalDateTime,
@Param("url") url: String? = null
): List<DailyViewStats>
以及 DailyViewStats 的数据类
data class DailyViewStats(
val date: LocalDate,
val viewCount: Long,
val uniqueVisitors: Long
) {
constructor(sqlDate: java.sql.Date, viewCount: Long, uniqueVisitors: Long) :
this(sqlDate.toLocalDate(), viewCount, uniqueVisitors)
}
我有一个“按 CAST 分组(pv.viewedAt 日期)”
我希望每个值都按日期分组,例如 2024 年 11 月 1 日的所有值
但是,当我记录结果时
val views = pageViewRepository.findDailyViewStatsBySiteAndInterval(site, startDate, endDate, null)
views.forEach { stat ->
println("Date: ${stat.date}, Views: ${stat.viewCount}, Unique: ${stat.uniqueVisitors}")
}
我有一个奇怪的结果,同一日期有许多记录,即使它是按日期分组的
Date: 2024-10-31, Views: 1, Unique: 1
Date: 2024-10-31, Views: 1, Unique: 1
Date: 2024-11-01, Views: 1, Unique: 1
Date: 2024-11-01, Views: 1, Unique: 1
Date: 2024-11-01, Views: 1, Unique: 1
所以我真的迷路了。我不明白为什么按功能分组没有按我的预期工作
SQLite 没有日期类型。它使用“类型亲和力”的概念来确定列应具有什么类型,但本质上任何列在任何特定时间都可以具有任何类型。当您(或 IDE)创建列 viewed_at
作为“日期”的表时,它实际上所做的是为其赋予关联性“数字”(
第 3.1 节,第 5 部分)。但是,该列实际包含的内容可能是数字,例如 Unix 纪元、ISO-8601 日期时间或任何其他受支持的格式。您应该在命令行上执行
select viewed_at from...
来检查列的格式,然后相应地修改您的查询。而不是 CAST(x AS date)
,您应该使用
date
函数:如果 x 是文本,则使用 date(x)
;如果 x 是数字,则使用 date(x, 'unixepoch')
。