在 Esqueleto 中获取聚合函数的结果

Posted

技术标签:

【中文标题】在 Esqueleto 中获取聚合函数的结果【英文标题】:Getting the result of aggregate functions in Esqueleto 【发布时间】:2014-09-18 10:42:53 【问题描述】:

假设我有以下模型:

Person
    ***User Bool
    age Int Maybe

使用 Esqueleto (& Yesod),假设我想获得 Stack Overflow 用户的平均年龄。我想用类型签名做一个函数:

userAge :: Handler (Maybe Int)

到目前为止,我有以下内容:

userAge :: Handler [Value (Maybe Int)]
userAge = runDB $
    select $
    from $ \person -> do
    where_ (person ^. Person***User ==. val True)
    return joinV $ avg_ (person ^. PersonAge)

这让我 [Value (Maybe Int)],但我需要深入了解“Maybe Int”。我试过做

mapM_ unValue userAge

但由于某种原因,这样做会引发类型错误,给我 [Maybe ()] 而不是 [Maybe Int]... 另外,我认为上面代码中的最后一行应该有:

person ?. PersonAge

而不是

person ^. PersonAge

因为 PersonAge 可以为 NULL,但更改它会给我一个类型错误,因为:

avg_ :: (PersistField a, PersistField b) => expr (Value a) -> expr (Value (Maybe b))
(^.) :: (PersistEntity val, PersistField typ) => expr (Entity val) -> EntityField val typ -> expr (Value typ)
(?.) :: (PersistEntity val, PersistField typ) => expr (Maybe (Entity val)) -> EntityField val typ -> expr (Value (Maybe typ))

这可能比我想象的要容易,但我无法在网上任何地方找到在 Esqueleto 中使用聚合函数的示例,而且我对 Haskell 很陌生,所以我很难弄清楚.

我想我可以只使用原始 SQL,但如果可能的话,我想使用 Esqueleto 来做到这一点。

【问题讨论】:

【参考方案1】:

知道了!最后把我的头绕在类型错误上并想出了这个:

import Safe (headMay)
import Control.Monad (join)
import Database.Esqueleto
-- other misc Yesod imports

userAge :: Handler (Maybe Int)
userAge = do
    a <- runDB $ select $
                 from $ \person -> do
                 where_ (person ^. Person***User ==. val True)
                 return $ joinV $ avg_ (person ^. PersonAge)
    return $ join (headMay (map unValue a))

“人 ^.PersonAge”似乎没有引起任何问题;我在空值和非空值上对其进行了测试。我猜是“?”运算符保留用于其他情况。

希望这可以节省其他人一些时间来弄清楚!

【讨论】:

以上是关于在 Esqueleto 中获取聚合函数的结果的主要内容,如果未能解决你的问题,请参考以下文章

如何使用单个 SQL 聚合函数查询为同一个聚合函数获取多个结果?

当聚合函数为空时,Sequelize 获取结果

无法使用 Spring Data JPA 执行聚合函数并获取结果

尝试使用 linq 聚合函数

26《MySQL 教程》聚合函数(聚合函数 MIN、MAX)

PCB MS SQL CLR聚合函数(函数作用,调用顺序,调用次数) CLR说明