我试图将以下SQL翻译成Esqueleto:
SELECT id, task_id, author_id
FROM scenario
INNER JOIN ( SELECT task_id as tId, author_id as aId, MAX(last_update) as lastUp
FROM scenario
GROUP BY task_id, author_id
) t
ON task_id = tId AND author_id = aId AND last_update = lastUp
要执行子查询,您必须使用subList_select。
我无法找到一种方法将它与模式匹配结合起来:
from $ \(s `InnerJoin` ?subQueryhere?) -> do ...
所以我尝试使用where_
代替:
where_ (s ^. ScenarioTaskId ==. (subList_select $
from $ \s' -> do
groupBy (s' ^. ScenarioTaskId, s' ^. ScenarioAuthorId)
return s'
) ^. ScenarioTaskId)
但是,由于subList_select
返回expr (ValueList a)
而不是expr (Entity Scenario)
,因此无法编译。
答案 0 :(得分:0)
我想我可以使用以下语义相同的内容(受this answer启发):
$ select
$ from $ \( s `LeftOuterJoin` ms ) -> do
on ( just (s ^. ScenarioAuthorId) ==. ms ?. ScenarioAuthorId &&.
just (s ^. ScenarioTaskId) ==. ms ?. ScenarioTaskId &&.
just (s ^. ScenarioLastUpdate) <. ms ?. ScenarioLastUpdate )
where_ (isNothing (ms ?. ScenarioId))
令我感到困惑的是,Esqueleto显然只支持多个结果的子查询,只与in_
结合使用...
答案 1 :(得分:0)
我也在为类似的事情苦苦挣扎。
您可以使用库的“实验性”模块(https://hackage.haskell.org/package/esqueleto-3.4.2.2/docs/Database-Esqueleto-Experimental.html 中的文档),它比普通 esqueleto 更强大(并且与普通 esqueleto 略有不同。
主要区别在于 from
- 你明确地告诉它你要加入什么,并且有很多选择。当您想谈论表格时,您还需要打开一个额外的扩展以使用 @TableName
标签。
我很想把所有的东西都改写成实验性的,除了由此产生的错误更难解决,因为你最终会使用更多的 do 符号。
无论如何,这是您可能需要的近似值:
(scenario :& (taskId, authorId) <-
from $ Table @Scenario `InnerJoin` SubQuery (do
scenario <- from $ Table @Scenario
groupBy (scenario ^. ScenarioTaskId, scenario ^. ScenarioAuthorId)
return (scenario ^. ScenarioTaskId, scenario ^. ScenarioAuthorId, max_(scenario ^. ScenarioLastUpdate))
)
`on` (\(scenario :& (taskId, authorId)) ->
(just (scenario ^. ScenarioTaskId) ==. just taskId) &&.
(just (scenario ^. ScenarioAuthorId) ==. authorId) &&.
(just (scenario ^. ScenarioLastUpdate) ==. lastUp)
)
return (scenario ^. ScenarioId, taskId, authorId)
可能需要在 just
子句中添加/删除 on
!我发现我需要的东西非常不直观。
还要小心使用 max_
(esqueleto)而不是 max
(标准库),否则会出现其他令人困惑的错误!