来自 Esqueleto 的唯一 post 作者
Unique post author from Esqueleto
我有一个 Esqueleto 查询 select 所有 StatusUpdate
及其各自的 User
。我想将其限制为每 User
仅一个 StatusUpdate
,并且从当天开始仅 StatusUpdate
s。
我有一个有效的 SQL 查询,我正在努力将其转换为有效的 Esqueleto。
SELECT "email", "subject"
FROM "status_update"
LEFT JOIN "user"
ON ("status_update"."user" = "user"."id")
WHERE "status_update"."id"
IN (SELECT MAX("status_update"."id") FROM "status_update" GROUP BY "status_update"."user")
我目前拥有的:
statusUpdates <- runDB
$ E.select
$ E.from $ \(status_update `E.LeftOuterJoin` user) -> do
E.on (status_update ^. StatusUpdateUser E.==. user ^. UserId)
E.where_ ((status_update ^. StatusUpdateId) `E.in_`
(E.subList_select $ E.from $ \(status_update) -> do
E.groupBy (status_update ^. StatusUpdateUser)
return (status_update ^. StatusUpdateId)))
return
( status_update ^. StatusUpdateId
, status_update ^. StatusUpdateSubject
, status_update ^. StatusUpdateMessage
, user ^. UserEmail
)
…产生以下输出:
SELECT "status_update"."id", "status_update"."subject", "status_update"."message", "user"."email"
FROM "status_update"
LEFT OUTER JOIN "user"
ON "status_update"."user" = "user"."id"
WHERE "status_update"."id"
IN (SELECT "status_update2"."id" FROM "status_update" AS "status_update2" GROUP BY "status_update2"."user"); []
似乎唯一缺少的是我的第二个 select 中的 MAX
函数。我一直在尝试将 E.max_
压缩到查询的不同部分,但我似乎无能为力。
帮忙?
而不是使用 subList_select
并尝试调用 max_
,您可以只使用 sub_select
并让子查询按日期排序并限制 1.
这是我找到的解决方案,似乎可以解决问题:
result <- select $ from $ \(user, status_update) -> do
let subquery = from $ \status_update2 -> do
where_ (status_update2 ^. StatusUpdateUser ==. user ^. UserId)
where_ (date (status_update2 ^. StatusUpdatePosted) ==. date now)
orderBy [desc (status_update2 ^. StatusUpdatePosted)]
limit 1
return (status_update2 ^. StatusUpdateId)
where_ (status_update ^. StatusUpdateId ==. sub_select subquery)
where_ (user ^. UserId ==. status_update ^. StatusUpdateUser)
return
( status_update ^. StatusUpdateId
, status_update ^. StatusUpdateSubject
, status_update ^. StatusUpdateMessage
, user ^. UserEmail
)
结果SQL是:
SELECT "status_update"."id", "status_update"."subject", "status_update"."message", "user"."email"
FROM "user", "status_update"
WHERE ("status_update"."id" = (SELECT "status_update2"."id"
FROM "status_update" AS "status_update2"
WHERE ("status_update2"."user" = "user"."id")
AND (date("status_update2"."posted") = date(date(?)))
ORDER BY "status_update2"."posted" DESC
LIMIT 1))
AND ("user"."id" = "status_update"."user")
为了满足 "only StatusUpdates
from the current day" 条件,我通过导入 Database.Esqueleto.Internal.Sql
和:
定义了 date
和 now
date :: SqlExpr (Value UTCTime) -> SqlExpr (Value Int)
date d = unsafeSqlFunction "date" d
now :: SqlExpr (Value UTCTime)
now = unsafeSqlFunction "date" (val "now" :: SqlExpr (Value String))
但是,"from the current day" 对您的确切含义可能有所不同(过去 24 小时、某个时区等)。
我有一个 Esqueleto 查询 select 所有 StatusUpdate
及其各自的 User
。我想将其限制为每 User
仅一个 StatusUpdate
,并且从当天开始仅 StatusUpdate
s。
我有一个有效的 SQL 查询,我正在努力将其转换为有效的 Esqueleto。
SELECT "email", "subject"
FROM "status_update"
LEFT JOIN "user"
ON ("status_update"."user" = "user"."id")
WHERE "status_update"."id"
IN (SELECT MAX("status_update"."id") FROM "status_update" GROUP BY "status_update"."user")
我目前拥有的:
statusUpdates <- runDB
$ E.select
$ E.from $ \(status_update `E.LeftOuterJoin` user) -> do
E.on (status_update ^. StatusUpdateUser E.==. user ^. UserId)
E.where_ ((status_update ^. StatusUpdateId) `E.in_`
(E.subList_select $ E.from $ \(status_update) -> do
E.groupBy (status_update ^. StatusUpdateUser)
return (status_update ^. StatusUpdateId)))
return
( status_update ^. StatusUpdateId
, status_update ^. StatusUpdateSubject
, status_update ^. StatusUpdateMessage
, user ^. UserEmail
)
…产生以下输出:
SELECT "status_update"."id", "status_update"."subject", "status_update"."message", "user"."email"
FROM "status_update"
LEFT OUTER JOIN "user"
ON "status_update"."user" = "user"."id"
WHERE "status_update"."id"
IN (SELECT "status_update2"."id" FROM "status_update" AS "status_update2" GROUP BY "status_update2"."user"); []
似乎唯一缺少的是我的第二个 select 中的 MAX
函数。我一直在尝试将 E.max_
压缩到查询的不同部分,但我似乎无能为力。
帮忙?
而不是使用 subList_select
并尝试调用 max_
,您可以只使用 sub_select
并让子查询按日期排序并限制 1.
这是我找到的解决方案,似乎可以解决问题:
result <- select $ from $ \(user, status_update) -> do
let subquery = from $ \status_update2 -> do
where_ (status_update2 ^. StatusUpdateUser ==. user ^. UserId)
where_ (date (status_update2 ^. StatusUpdatePosted) ==. date now)
orderBy [desc (status_update2 ^. StatusUpdatePosted)]
limit 1
return (status_update2 ^. StatusUpdateId)
where_ (status_update ^. StatusUpdateId ==. sub_select subquery)
where_ (user ^. UserId ==. status_update ^. StatusUpdateUser)
return
( status_update ^. StatusUpdateId
, status_update ^. StatusUpdateSubject
, status_update ^. StatusUpdateMessage
, user ^. UserEmail
)
结果SQL是:
SELECT "status_update"."id", "status_update"."subject", "status_update"."message", "user"."email"
FROM "user", "status_update"
WHERE ("status_update"."id" = (SELECT "status_update2"."id"
FROM "status_update" AS "status_update2"
WHERE ("status_update2"."user" = "user"."id")
AND (date("status_update2"."posted") = date(date(?)))
ORDER BY "status_update2"."posted" DESC
LIMIT 1))
AND ("user"."id" = "status_update"."user")
为了满足 "only StatusUpdates
from the current day" 条件,我通过导入 Database.Esqueleto.Internal.Sql
和:
date
和 now
date :: SqlExpr (Value UTCTime) -> SqlExpr (Value Int)
date d = unsafeSqlFunction "date" d
now :: SqlExpr (Value UTCTime)
now = unsafeSqlFunction "date" (val "now" :: SqlExpr (Value String))
但是,"from the current day" 对您的确切含义可能有所不同(过去 24 小时、某个时区等)。