beam icon indicating copy to clipboard operation
beam copied to clipboard

Multicolumn aggregate

Open yaitskov opened this issue 2 years ago • 1 comments

Hi,

I would like to have 3 aggregated columns. A query with 2 aggregate columns is defined as:

import Data.Bifunctor qualified as BF
import Database.Beam
import Database.Beam.Backend.SQL.BeamExtensions (runInsertReturningList)
import Database.Beam.Postgres
import Database.PostgreSQL.Simple
import Database.PostgreSQL.Simple.Types

userDataTableDigestQ :: UserTable -> SqlSelect
  Postgres (UserDataTable, UserDataTable)
userDataTableDigestQ ut = select ag
  where
    al = all_ (userDataTableRef $ usertableName ut)
    ag = subselect_ $ aggregate_
      (BF.bimap group_ group_)
      ((,)
        <$> limit_ 1 (orderBy_ (asc_ . userdatatableTs) al)
        <*> limit_ 1 (orderBy_ (desc_ . userdatatableTs) al))

To get 3 column logical solution is to use trimap/Trifunctor, but there is no such function/class on hoogle, so I am worried that this might be wrong way to go.

yaitskov avatar Jun 06 '23 14:06 yaitskov

Trifunctor works

class Trifunctor p where
  trimap :: (a -> d) -> (b -> e) -> (c -> f) -> p a b c -> p d e f

instance Trifunctor (,,) where
  trimap fa fb fc ~(a, b, c) = (fa a, fb b, fc c)

but group_ and countAll_ don't fit together even for 2 columns

userDataTableDigestQ3 :: UserTable -> SqlSelect
  Postgres (UserTable, Int32)
userDataTableDigestQ3 ut = select ag
  where
    al = all_ (userDataTableRef $ usertableName ut)
    ag = subselect_ $ aggregate_
      (BF.bimap group_ (\_ -> as_ @Int32 countAll_))
      ((,)
        <$> limit_ 1 (orderBy_ (asc_ . userdatatableTs) al)
        <*> al)

yaitskov avatar Jun 06 '23 15:06 yaitskov