【问题标题】:Any string concatenation method in slick groupBy?slick groupBy中的任何字符串连接方法?
【发布时间】:2017-03-03 17:23:49
【问题描述】:

我正在尝试在 Slick 查询中应用 .groupBy

var q = (for {
      user <- Users
      userSettings <- UserSettings if user.id === userSettings.userId
    } yield (user, userSettings)).groupBy {
      case (users, userSettings) =>
        (user.id, userSettings.controls)
    }.map {
      case (x, y) => (x._1, y.map(_._2.controls).???)
    }

如果controls 列是整数或长整数,我可以应用sumavg 和其他聚合函数。但在这种情况下,controls 是一个字符串。如何对这些字符串进行分组连接,使记录看起来像

-----------------------------------------
|User ID    |User Controls              |
-----------------------------------------
|1          |left, right, up, down      |
|2          |left, right                |
-----------------------------------------

不应用groupBy 记录看起来像这样

-----------------------------------------
|User ID    |User Controls              |
-----------------------------------------
|1          |left                       |
|1          |right                      |
|1          |up                         |
|1          |down                       |
|2          |left                       |
|2          |right                      |
-----------------------------------------

【问题讨论】:

标签: scala playframework slick


【解决方案1】:

Slick 获取您的 Scala 代码并将其转换为 SQL,因此您在 Slick 中所做的任何事情都必须得到底层 SQL 的支持。如果您在 SQL 中搜索与连接字符串相关的类似问题,请find some results on SO。不幸的是,在 SQL 中做这种事情并非易事。 (注意:在某些 SQL 方言中是可能的。)可能有一些 Slick 驱动程序公开了 SQL 方言特定的功能,或者在 SQL 查询之后执行的东西,但您可以简单地进行查询,并在对数据库执行 groupBy/map 后运行它,例如:

val q = for {
  user <- Users
  userSettings <- UserSettings if user.id === userSettings.userId
} yield (user.id, userSettings.controls)
val db = Database.forConfig("h2mem1")
try {
  for {
    res <- db.run(q.result)
  } yield res
    .groupBy(_._1)
    .map({ case (id, t) => id -> t.map(_._2).mkString(", ") })
} finally db.close

【讨论】:

  • 我想在运行db.run之前应用搜索排序@
  • IIRC — 如果行在从db.run 返回时已排序,则 Scala 的 groupBy() 应保持分组内的顺序。
【解决方案2】:

很遗憾,没有注意到对此的支持。在这种情况下,我们可以使用经过适当验证和清理的原始查询。

假设,我有一个名为logs(id、消息、日期)的表。我想按日期分组并联系每个组消息。所以我的查询是:

def histogram(data: ReqData): Future[Vector[DbHistogramMapper]] = {

    var messageWild = s"%${data.phrase}%"
    /**Need to write raw query because there is no support for GROUP_CONCAT in slick*/
    val query = sql"""SELECT "date" AS date, GROUP_CONCAT("message") AS message FROM "logs" WHERE "date" >= ${data.datetimeFrom} AND "date" <= ${data.datetimeUntil} AND "message" LIKE  ${messageWild} GROUP BY "date" """.as[DbHistogramMapper]
    db.run(query)
  }

注意:DbHistogramMapper

case class DbHistogramMapper(
     date: Timestamp,
     message: String
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-14
    • 2022-04-06
    • 1970-01-01
    • 2015-02-02
    相关资源
    最近更新 更多