Esqueleto: присоединиться к подзапросу (используя subList_select)
Я пытаюсь перевести следующий 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)
,
2 ответа
Я боролся с похожей проблемой.
Вы можете использовать «экспериментальный» модуль библиотеки, который немного мощнее обычного 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
s в
on
пункт может быть необходим! Я нашел то, что мне было нужно, очень не интуитивно понятным.
Также будьте осторожны при использовании
max_
(esqueleto) а не
max
(стандартная библиотека), иначе у вас будут другие запутанные ошибки!
Я думаю, я могу использовать следующее, которое должно быть семантически идентичным (вдохновленный этим ответом):
$ 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_
...