如何让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
在查询表达式中?我提出了
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, ???) }
但是我无法弄清楚要插入" ???"。更糟糕的是,"得分" column可以为null,这会使数学变得复杂。
或者,有更简单的方法吗?我对.NET数据库访问不是很熟悉。理想情况下,我只是给它一块SQL,它会解析它,并吐出一些类型的数据。实际上,试图找出简单SQL的非SQL语法非常令人沮丧。
答案 0 :(得分:5)
对SQL的转换通常可以更好地处理C#样式的LINQ操作,而不是使用本机F#函数。因此,使用Select
和Average
扩展方法比使用Seq.map
和Seq.average
等标准F#函数更容易。
我尝试使用示例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
它生成的查询有点复杂,但看起来正确(并在SQL端使用CASE
)。您可以通过设置db.DataContext.Log <- System.Console.Out
。
通常应该使用的另一件事是使用嵌套查询,但我没有尝试过。
答案 1 :(得分:0)
现在好几年了,但从来没有太晚?这有什么帮助吗?特别要注意FirstOrDefault的使用。对不起挪威的名字,但这并不重要。 “x”表示访问第一个表。
type Result3 = { Aarsak: int; Beskrivelse: string; Antall: int; Varighet: Nullable<int> }
let query3 = query {
for stopptid in dc.StoppTider do
where (stopptid.DatoS = datoS && stopptid.SkiftNr = skiftNr)
groupBy stopptid.Aarsak into g
join stoppaarsak in dc.StoppAarsak on (g.FirstOrDefault().Aarsak.ToString() = stoppaarsak.Nr)
select { Aarsak = g.Key; Beskrivelse = stoppaarsak.Norsk; Antall = g.Count(); Varighet = g.Sum(fun x -> x.Varighet) }
}
谷歌搜索时我第一次来到这里。由于它没有帮助,我用C#搜索了相同的解决方案,得到了SO的打击,让它在C#中为我的情况工作,然后在F#中。这是链接: