2014-05-11 4 views
1

Esquleto에서 예제 쿼리 중 하나를 사용하려고하지만 컴파일 할 수 없습니다. 유일한 변형은 내가 조인하지 않고 사용한다는 것입니다.Esqueleto 쿼리에서 그룹 By 및 Sum 사용 방법

sqlite> select * from my_table; 
id|category|amount 
1|A|1.0 
2|A|2.0 
3|B|2.0 
4|B|8.0 

그리고이 무엇을 하시겠습니까 : 이것은 내 쿼리

select category,sum(amount) from my_table group by category; 
category|sum(amount) 
A|3.0 
B|10.0 

입니다 :

내가 이렇게 보이는 테이블이

import qualified Database.Esqueleto as E 

r <- runDB $ 
    E.select $ E.from $ \t -> do 
     E.groupBy $ t E.^. MyTableCategory 
     let sum' = E.sum_ (t E.^. MyTableAmount) 
     E.orderBy [E.desc sum'] 
     return (t E.^. MyTableCategory, sum') 

나는이를 얻을 수 오류 :

No instance for (PersistField b0) arising from a use of `E.select' 
The type variable `b0' is ambiguous 
Possible fix: add a type signature that fixes these type variable(s) 
Note: there are several potential instances: 
    instance PersistField Account -- Defined in `Model' 
    instance PersistField AccountCategory -- Defined in `Model' 
    instance PersistField MyTable -- Defined in `Model' 
    ...plus 37 others 
In the expression: E.select 
In the second argument of `($)', namely 
    `E.select 
    $ E.from 
    $ \ t 
     -> do { E.groupBy $ t E.^. MyTableCategory; 
       let ...; 
       .... }' 
In a stmt of a 'do' block: 
    r <- runDB 
     $ E.select 
     $ E.from 
      $ \ t 
       -> do { E.groupBy $ t E.^. MyTableCategory; 
         let ...; 
         .... } 

E.select에 대한 유형 정보는 어디에서 제공합니까? 컴파일러가 t E.^.MyTableCategory에서 추론 할 수 있어야합니까? 나는 또한 countRows/groupBy 예제를 사용하여 여기 (https://hackage.haskell.org/package/esqueleto-1.4.1/docs/Database-Esqueleto.html)하지만 비슷한 문제 (유일한 차이점은 제가 조인이 없다는 것입니다)

당신의 도움에 감사드립니다.

감사합니다.

+0

컴파일 당신이 당신의 * 모델 * 엔티티 목록을 보여줄 수 있습니까? –

답변

4

테이블 매개 변수 유형은 명시 적이어야하는 결과 유형에서 추론되는 경우가 있습니다.

일반적으로 모나드 유형에 대해서는 다른 모호성이 발생합니다.

일부 모호성을 해결하기 위해 쿼리를 특정 함수로 묶는 것이 유용합니다.

내가 지금 esqueleto 쿼리 적합성을 인증 할 수는 없지만

이 시도 :

{-# LANGUAGE PackageImports, ConstraintKinds #-} 

import Import 
import "esqueleto" Database.Esqueleto as E 
import "monad-logger" Control.Monad.Logger (MonadLogger) 
import "resourcet" Control.Monad.Trans.Resource (MonadResourceBase) 

type TCategory = Text -- change it if its different 
type TAmount = Double 

myQuery :: (PersistQuery (SqlPersist m), MonadLogger m , MonadResourceBase m) => 

         SqlPersist m [(E.Value TCategory, E.Value (Maybe TAmount))] -- corrected 
myQuery = do 

    -- your query 

    E.select $ E.from $ \t -> do 
     E.groupBy $ t E.^. MyTableCategory 
     let sum' = E.sum_ (t E.^. MyTableAmount) 
     E.orderBy [E.desc sum'] 
     return (t E.^. MyTableCategory, sum') 

-- within your handler: 

    pairListResult <- runDB myQuery 

    forM_ pairListResult $ \(E.Value categ, E.Value maybeAmount) -> do -- whatever 

업데이트 : 그것은

+0

고맙습니다. @ 가브리엘. 추가 형식 주석이있는 이전 버전 (t에 있음)은 여전히 ​​컴파일되지 않았지만이 형식은 않습니다! 나는 왜 컴파일러에게 더 많은 정보를주는 것이 나쁜 것인지는 잘 모르겠다. :) Btw,'SqlPersist'가 deprecated되어'SqlPersistT'로 전환했고 그것도 작동하는 것처럼 보입니다. 다시 한번 감사드립니다. 나 혼자서 알아 내지 못했을거야. – Ecognium