在Esqueleto中联接子查询的结果

时间:2018-10-03 10:48:13

标签: haskell esqueleto

我要翻译的查询的必要部分如下:

SELECT c.id, c.name, officer.id, officer.name
FROM (
  SELECT DISTINCT ON (company.number) company.id, company.name
  FROM company
  ORDER BY company.number DESC
  LIMIT 15
) AS c
INNER JOIN officer ON c.id = officer.company_id;

我正在尝试的Esqueleto(无法编译)如下:

query mLocation = E.select $ E.from $
  \o -> do
    let sub = E.subList_select
              $ E.from
              $ \(c `E.LeftOuterJoin` cc `E.LeftOuterJoin` l) -> do
                E.distinctOn [ E.don (c E.^. CompanyNumber) ] $ do
                  E.on $ c E.^. CompanyPostcode E.==. l E.^. LocationPostcode
                  E.on $ c E.^. CompanyId E.==. cc E.^. CompanyCategoryCompany
                  whereRegisteredFrom c (queryFilterFromDate qf)
                  whereRegisteredTo c (queryFilterToDate qf)
                  whereLikeTerm c (queryFilterSearchTerm qf)
                  whereVisible c
                  whereWithinRadiusOf (queryFilterRadius qf) mLocation

                  let categories' = map (\(QueryCategory a) -> a) (fromMaybe [] $ queryFilterCategories qf)
                      subQuery = E.subList_select $ E.from $ \cat -> do
                                 E.where_ $ cat E.^. CategoryCode `E.in_` E.valList categories'
                                 return $ cat E.^. CategoryId

                  when (isJust (queryFilterCategories qf))
                    (E.where_ $ cc E.^. CompanyCategoryCategory `E.in_` subQuery)

                  E.limit (fromInteger limit)
                  E.offset $ (fromInteger page - 1) * (fromInteger limit)
                  E.orderBy [ E.desc (c E.^. CompanyNumber) ]
                  return c
    E.on $ sub E.^. CompanyId E.==. o E.^. OfficerCompanyId
    return (sub, o)

1 个答案:

答案 0 :(得分:0)

最终解决了这个问题:

query :: Maybe Location -> DB [(Entity Company, Entity Officer)]
query mLocation = E.select $ E.from $ \(c' `E.InnerJoin` o) -> do
  let sub = E.subList_select $ E.from
            $ \(c `E.LeftOuterJoin` cc `E.LeftOuterJoin` l) -> do
              E.distinctOn [ E.don (c E.^. CompanyNumber) ] $ do
                E.on $ c E.^. CompanyPostcode E.==. l E.^. LocationPostcode
                E.on $ c E.^. CompanyId E.==. cc E.^. CompanyCategoryCompany
                whereRegisteredFrom c (queryFilterFromDate qf)
                whereRegisteredTo c (queryFilterToDate qf)
                whereLikeTerm c (queryFilterSearchTerm qf)
                whereVisible c
                whereWithinRadiusOf (queryFilterRadius qf) mLocation

                let categories' = map (\(QueryCategory a) -> a) (fromMaybe [] $ queryFilterCategories qf)
                    subQuery = E.subList_select $ E.from $ \cat -> do
                               E.where_ $ cat E.^. CategoryCode `E.in_` E.valList categories'
                               return $ cat E.^. CategoryId

                when (isJust (queryFilterCategories qf))
                  (E.where_ $ cc E.^. CompanyCategoryCategory `E.in_` subQuery)

                E.limit (fromInteger limit)
                E.offset $ (fromInteger page - 1) * (fromInteger limit)
                E.orderBy [ E.desc (c E.^. CompanyNumber) ]
                return $ c E.^. CompanyId
  E.on $ c' E.^. CompanyId E.==. o E.^. OfficerCompanyId
  E.where_ $ c' E.^. CompanyId `E.in_` sub
  return (c', o)