Как использовать Group By и Sum в Esqueleto Query

Я пытаюсь использовать один из примеров запросов от Esqueleto, но не могу его скомпилировать. Единственный вариант - я использую его без соединения.

У меня есть таблица, которая выглядит так:

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), но похожая проблема (единственное отличие состоит в том, что у меня нет соединения)

Ценю твою помощь.

Спасибо!

1 ответ

Решение

Типы параметров из таблицы иногда выводятся из типа результата, который должен быть явным.

Обычно возникают другие неясности относительно типа монады.

Полезно заключить запрос в определенную функцию, чтобы решить некоторые неясности.

Я не могу подтвердить соответствие вашего запроса 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

Обновление: компилируется

Другие вопросы по тегам