我怎样才能让F#做到相当于
select a.id, avg(case when a.score = b.score then 1.0 else 0.0 end)
from table1 a join table2 b on a.id = b.id and a.date = b.date
group by a.id
Run Code Online (Sandbox Code Playgroud)
在查询表达式?我想出来了
query {
for a in db.table1 do
join b in db.table2 on ((a.id, a.date) = (b.id, b.date))
groupBy a.id into g
select (g.Key, ???) }
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚要插入"???"的内容.更糟糕的是,"得分"列可以为空,这使数学变得复杂.
或者,是否有更简单的方法来做到这一点?我对.NET数据库访问不是很熟悉.理想情况下,我只是给它一块SQL,它会解析它,并吐出一些类型的数据.实际上,试图找出简单SQL的非SQL语法非常令人沮丧.
对于C#样式的LINQ操作,SQL的转换通常可以比使用本机F#函数更好地处理.所以它更容易去Select
和Average
扩展方法比用像标准的F#的功能Seq.map
和Seq.average
.
我尝试使用示例Northwind数据库编写类似的分组 - 我没有找到很好的表来加入,但以下做基本聚合CASE
并且工作正常:
open System.Linq
query {
for p in db.Products do
groupBy p.CategoryID.Value into g
select (g.Key, g.Select(fun a ->
if a.UnitPrice.Value > 10.0M then 1.0 else 0.0).Average()) }
|> Array.ofSeq
Run Code Online (Sandbox Code Playgroud)
它生成的查询有点复杂,但看起来正确(并CASE
在SQL端使用).你可以通过设置看到db.DataContext.Log <- System.Console.Out
.
通常应该工作的另一件事是使用嵌套查询,但我没有尝试过.