如何在Slick中执行以下sql语句。问题是在select语句中有过滤器,我不知道如何在Slick中进行过滤。
SELECT Sellers.ID,
COALESCE(count(DISTINCT Produce.IMPORTERID) FILTER (WHERE Produce.CREATED > '2019-04-30 16:38:00'), 0::int) AS AFTERDATE,
COALESCE(count(DISTINCT Produce.IMPORTERID) FILTER (WHERE Produce.NAME::text = 'Apple'::text AND Produce.CREATED > '2018-01-30 16:38:00'), 0::bigint) AS APPLES
FROM Sellers
JOIN Produce ON Produce.SellersID = Sellers.ID
WHERE Sellers.ID = 276
GROUP BY Sellers.ID;
答案 0 :(得分:0)
尝试
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import slick.jdbc.PostgresProfile.api._
case class Seller(id: Long)
case class Produce(name: String, sellerId: Long, importerId: Long, created: LocalDateTime)
class Sellers(tag: Tag) extends Table[Seller](tag, "Sellers") {
def id = column[Long]("ID", O.PrimaryKey)
def * = id <> (Seller.apply, Seller.unapply)
}
class Produces(tag: Tag) extends Table[Produce](tag, "Produce") {
def name = column[String]("NAME", O.PrimaryKey)
def sellerId = column[Long]("SellersID")
def importerId = column[Long]("IMPORTERID")
def created = column[LocalDateTime]("CREATED")
def * = (name, sellerId, importerId, created) <> (Produce.tupled, Produce.unapply)
}
val sellers = TableQuery[Sellers]
val produces = TableQuery[Produces]
val dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
val ldt2019 = LocalDateTime.parse("2019-04-30 16:38:00", dtf)
val ldt2018 = LocalDateTime.parse("2018-01-30 16:38:00", dtf)
sellers.join(produces).on(_.id === _.sellerId)
.filter { case (s, p) => p.sellerId === 276L }
.groupBy { case (s, p) => s.id }
.map { case (sid, group) =>
(
sid,
group
.filter { case (s, p) => p.created > ldt2019 }
.map { case (s, p) => p.importerId }
.distinct.length,
group
.filter { case (s, p) => p.name === "Apple" && p.created > ldt2018 }
.map { case (s, p) => p.importerId }
.distinct.length
)
}
libraryDependencies += "com.github.tminglei" %% "slick-pg" % "0.18.0"
答案 1 :(得分:0)
我真的希望像@Dymytro的答案一样有效,但是从我的测试来看,一切都归结于GROUP BY
的局限性,这是您将遇到的问题:
Slick
与Postgres驱动程序配合使用将不起作用,因为Slick不支持带有FILTER子句的聚合函数。 Postgres是少数支持FILTER的数据库之一!所以你不会走得太远:someQuery
.groupBy { a => a.pivot }
.map{ case (pivot, query) =>
(
pivot,
query
.filter(_.condition === "stuff")
.map(_.column).distinct.length
)
}
尽管可以编译,但您会遇到类似以下的运行时错误:
[错误] slick.SlickTreeException:无法将节点转换为SQL理解
slick-pg
,就会发现它支持Postgres聚合函数!包括FILTER
子句!但是... aggregate functions with GROUP BY有一个未解决的问题,因此这种尝试也将失败:import com.github.tminglei.slickpg.agg.PgAggFuncSupport.GeneralAggFunctions._
...
someQuery
.groupBy { a => a.pivot }
.map{ case (pivot, query) =>
(
pivot,
query
.map(a => count(a.column.distinct).filter(a.condition === "stuff"))
)
}
未找到匹配的形状。 [错误] Slick不知道如何映射给定的类型。
因此,幸运的是,简单的单列 FILTER
expressions can be equivalently implemented with the more primitive CASE
statements解决了这些问题或有人发布了解决方法。虽然不那么漂亮,但是可以正常工作!
val caseApproach = someQuery
.groupBy { a => a.pivot }
.map{ case (pivot, query) =>
(
pivot,
query
.map{ a =>
Case If a.condition === "stuff" Then a.column
}.min //here's where you add the aggregate, e.g. "min"
)
}
println(caseApproach.result.statements.headOption)
从数据透视表组中依次选择数据透视表min(((((condition)='stuff')然后是“ column” end)时的情况)