4

我有一个混合了整数和浮点列的 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

添加信息

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

更多附加信息

异常详情:

System.Exception 未处理 消息:在 >FSharp.Core.dll 中发生了“System.Exception”类型的未处理异常附加信息:不支持的执行表达式value(FSharp.Data.Sql.Runtime.QueryImplementation+SqlQueryable1[FSharp.>Data.Sql.Common.SqlEntity]).Min(row = > >Convert(Convert(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

2017 年 2 月 1 日更新

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

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

2 回答 2

2

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

let x = query {for row in db do
                sortBy row.Column
                take 1
                select row.Column } |> Seq.head
于 2017-02-01T19:39:44.387 回答
0

您需要将输出列强制为intor float(无论您需要还是给您带来麻烦)。您还需要注意以防您的任何列可以为空。下面的示例将强制列为floatfirst (以确保可以为空),然后将其转换为int,最后得到最小值:

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

当然,您可能想更改顺序,或者只是说float Mycolumn.

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

于 2017-01-31T00:07:44.510 回答