【问题标题】:F# Query, Group Multiple Values by Single ColumnF# 查询,按单列分组多个值
【发布时间】:2014-04-17 02:32:03
【问题描述】:

我有一个 F# sql 查询,需要对每组中的两列求和。

let financials = query{
        for data in dbData do
        groupValBy (data.earning, data.losses) data.store into group
        select (group.Key, group.Sum(fun (group) -> fst group), group.Sum(fun (group) -> snd group))
    }

我还没有找到任何关于如何做到这一点的例子,但是这段代码编译得很好,而且根据每一个迹象,它应该可以工作。但是,在执行时,我总是收到一条异常消息“无法格式化节点'新'以执行为 SQL。”如果我删除 data.losses 一切正常,但添加第二个值会导致错误。还有另一种方法可以做到这一点吗?建议将不胜感激。

注意,这个问题类似,但处理的是多列分组的相反情况:groupby multiple columns in a F# 3.0 query

更新:

我还尝试了以下方法:

(NewAnonymousObjectHelper(T(data.earning, data.losses)))

其中 T 是:

type T(earning : decimal, losses : decimal) =
    member val Earning=earning with get,set
    member val Losses=losses with get,set

但是,需要创建一个接受类型 T 的新 Sum 函数。我也尝试过使用 F# PowerPack 中的 MutableTuple,但未能让它识别 MutableTuple(对此代码/dll 和关联的命名空间不太熟悉)。但它似乎应该工作:

let t = MutableTuple<_,_>(item1=data.earning,item2=data.losses)
groupValBy t data.store into group

也许有人可以就我在这里遗漏的内容提出建议。

结论:

看起来像在选择之前使用 let 对结果求和是要走的路。不清楚为什么 group.Sum() 不能在选择行上工作。 (注意:我上面提到的错误消息是由一些 sql server 问题引起的。)

【问题讨论】:

    标签: types f# provider


    【解决方案1】:

    这可能是另一种仅使用 groupBy 的解决方案,但仅使用 linq to objects 对其进行了测试。

    type Data =
        {Store : string; Earning : float; Losses : float }
    
    let dbData =
        [| { Store = "Store A"; Earning = 5.0; Losses = 2.0 }
           { Store = "Store A"; Earning = 10.0; Losses = 3.0 }
           { Store = "Store B"; Earning = 3.0; Losses = 1.0 } |]
    
    let financials =
        query {
            for data in dbData do
            groupBy data.Store into group
            let earnings = query { for g in group do sumBy g.Earning }
            let losses = query { for g in group do sumBy g.Losses }
            select (group.Key, earnings, losses) } |> Seq.toArray
    

    【讨论】:

      【解决方案2】:

      虽然我不得不承认,我还没有测试过这个 - 我感觉这样的东西可能会起作用:

      let financials =
          query {
              for data in dbData do
              groupValBy (data.earning, data.losses) data.store into group
              let earnings = query { for (e,_) in group do sumBy e }
              let losses = query { for (_,l) in group do sumBy l }
              select (group.Key, earnings, losses) }
      

      this site 上的示例启发。您可能想改用sumByNullable

      【讨论】:

      • 我认为您需要将参数 data.store 和 (data.earning, data.losses) 像“groupValBy (data.earning, data.losses) data.store 切换到组”
      • 快速谷歌搜索后,我可以看到你(可能)是对的。:) 正如我所说,我没有测试过。我已经编辑了我的建议。我现在应该做这项工作。
      • 是的,这确实有效。我只是不明白为什么 group.Sum(fun (e,_) -> e) 代替选择行上的收入不起作用。感谢您的帮助...
      • 当我将 GOP 的原始程序连接到数据对象而不是 SQL 数据库时,它适用于我。我有兴趣解释为什么首先存在 SQL 问题以及您的解决方案如何提供帮助?
      猜你喜欢
      • 1970-01-01
      • 2012-01-28
      • 2015-12-31
      • 1970-01-01
      • 1970-01-01
      • 2013-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多