【问题标题】:f# sqlite sqlprovider minBy maxBy using floatf# sqlite sqlprovider minBy maxBy using float
【发布时间】:2017-06-16 06:15:20
【问题描述】:

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

错误是:System.InvalidCastException发生在FSharp.Core.dll

添加信息

我创建了一个新表,其中有一列浮点类型。我插入了值 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

2/1/17 更新

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

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

【问题讨论】:

  • 您是否尝试过将输出包装在float 中(强制)。例如。 float row.NumCatsfloat row.CatHeight?
  • 您能提供更多信息吗?
  • 很好,但我的意思是异常消息和一些围绕它的代码
  • 我添加了更多异常信息和我用来测试它的整个代码
  • 我可以使用 Sqlite 以及最新版本的 sqlprovider 和 sqlite.core 重现您的问题。也许你应该提出一个问题。现在您可以做的是将查询通过管道传输到|&gt; Seq.minBy,但正如您所说的性能方面可能很困难。

标签: f# double fsharp.data.sqlclient


【解决方案1】:

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

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

当然,您可能想更改顺序,或者直接说float Mycolumn

更新: 使用 Sqlite 确实会导致错误。你可能想做query { ... } |&gt; Seq.minBy 来提取最小的数字。

【讨论】:

  • 感谢您提供正确的语法,但不幸的是,它也失败了。我还尝试在我的数据库中只使用一行来确保如果浮点列的值都是十进制的。如果有其他方法可以解决这个问题,我愿意接受任何事情。
【解决方案2】:

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

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

【讨论】:

  • 你能检查一下 1.0.42,好像是fix is in
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-26
  • 2022-12-27
  • 1970-01-01
相关资源
最近更新 更多