如何用Esqueleto撰写查询/子选择?

时间:2015-09-03 16:01:57

标签: sql haskell subquery esqueleto

根据this answer,我得出结论,Esqueleto不允许使用left outer join撰写两个查询。但是,我希望在某个地方仍能解决我的问题。

我想使用另外受限制的表进行左外连接。考虑我的第一种方法:

fetchFarmsByCity1 city = runDb . select . from $
  \(farm `LeftOuterJoin` pig) -> do
    on $ pig ?. PigFkFarm ==. just (farm ^. FarmId)
    where_ $
          pig ?. PigNumberOfLegs ==. val 4
      &&. farm ^. FarmCity ==. val city
    return (farm, pig)
  • 我得到了所有农场和他们的四条腿猪。
  • 即使他们根本没有任何猪,我也会得到农场(感谢左外连接)。
  • 但是,我没有那个有2条腿,3条腿或5条腿的猪的农场,但这就是我所需要的:如果猪有3条腿,我想要没有任何猪的农场。

我的第二种方法是一个sql驱动的子查询,在类型检查期间已经失败,可能是因为此帖子顶部链接的限制:

pigsQuery = from $ \pig -> do
  where_ $ pig ^. PigNumberOfLegs ==. val 4
  return pig

fetchFarmsByCity2 city = runDb . select . from $
  \(farm `LeftOuterJoin` pig) -> do
    pigs <- pigsQuery
    on $ pig ?. PigFkFarm ==. just (farm ^. FarmId)
    where_ $
          farm ^. FarmCity ==. val city

还有另一种解决方法吗?我可以以某种方式在外连接前移动腿数限制(在第一种方法中)吗?将它分成两个查询将是我的最后手段。

我觉得这很标准,可以提供其他解决方案。

1 个答案:

答案 0 :(得分:2)

似乎通过移动&#34; 4腿&#34;限制on子句而不是where_子句:

fetchFarmsByCity1 city = select . from $
  \(farm `LeftOuterJoin` pig) -> do
    on $
        (pig ?. PigFkFarm ==. just (farm ^. FarmId)
        &&. (pig ?. PigNumberOfLegs ==. just (val 4)))
    where_ $
      farm ^. FarmCity ==. val city
    return (farm, pig)