f#sqlite sqlprovider minBy maxBy using float

时间:2017-01-30 22:58:44

标签: f# double fsharp.data.sqlclient

我有一个带有整数和浮点列的sqlite表。我正在尝试获取每列的最大值和最小值。对于整数列,以下代码可以正常工作,但在浮点列上使用相同的代码时会出现转换错误:

let numCats = query{for row in db do minBy row.NumCats}

对于浮动列,我使用以下代码,但速度很慢。

let CatHight = query{for row in db do select row.CatHeight} |> Seq.toArray |> Array.max

我有8个整数列和9个浮点列,并且所有列的行为都是一致的,这就是为什么我认为这是列类型的问题。但我是F#的新手并且什么都不知道,所以我希望你能帮助我。

感谢您抽出宝贵时间提供帮助,非常感谢。

SQLProvider版本:1.0.41

System.Data.SQLite.Core版本:1.0.104

错误是:FSharp.Core.dll

中发生了System.InvalidCastException

已添加信息

我用一个float类型的列创建了一个新表。我插入了值2.2和4.2。使用SQLProvider和System.Data.SQLite.Core我连接使用minBy或maxBy查询数据库,我得到强制转换异常。如果列类型是整数,则它可以正常工作。

更多已添加信息

例外细节:

  

System.Exception未处理   消息:> FSharp.Core.dll中出现未处理的“System.Exception”类型异常   附加信息:不支持的执行表达式value(FSharp.Data.Sql.Runtime.QueryImplementation+SqlQueryable 1 [FSharp。> Data.Sql.Common.SqlEntity])。Min(row =>>转换(转换(row.GetColumn(“X”)))) `

失败的代码:

open FSharp.Data.Sql

[<Literal>]
let ConnectionString =
"Data Source=c:\MyDB.db;" +
"Version=3;foreign keys=true"

type Sql = SqlDataProvider<Common.DatabaseProviderTypes.SQLITE,
ConnectionString,
//ResolutionPath = resolutionPath,
CaseSensitivityChange = Common.CaseSensitivityChange.ORIGINAL>

let ctx = Sql.GetDataContext()
let Db = ctx.Main.Test

let x = query{for row in Db do minBy row.X}
printfn "x: %A" x

更新2/1/17

另一位用户能够重现该问题,因此我向SQLProvider提交了一个问题。我现在正在寻找解决方法,虽然下面的代码工作且速度很快,但我知道有更好的方法 - 我找不到正确的方法。如果有人用更好的代码回答,我会接受这个答案。再次感谢所有的帮助。

let x = query {for row in db do
                sortBy row.Column
                take 1
                select row.Column } |> Seq.toArray |> Array.min

2 个答案:

答案 0 :(得分:2)

这是我的解决方法,@ s952163和SO f#聊天室的好人帮助了我。再次感谢所有帮助过的人。

let x = query {for row in db do
                sortBy row.Column
                take 1
                select row.Column } |> Seq.head

答案 1 :(得分:0)

您需要将输出列强制转换为intfloat(无论您需要或给您带来麻烦)。如果您的任何列都可以为空,您还需要注意。下面的示例将首先将列强制转换为float(以便可以为空),然后将其转换为int,最后得到最小值:

let x = query { for row in MYTABLE do
                minBy (int (float row.MYCOLUMN))}

您可能想要更改课程顺序,或只是说float Mycolumn

<强>更新 使用Sqlite确实会导致错误。您可能希望query { ... } |> Seq.minBy提取最小的数字。