简体   繁体   English

f#sqlite sqlprovider minBy maxBy using float

[英]f# sqlite sqlprovider minBy maxBy using float

I have a sqlite table with a mix of integer and float columns. 我有一个带有整数和浮点列的sqlite表。 I'm trying to get the max and min values of each column. 我正在尝试获取每列的最大值和最小值。 For integer columns the following code works but I get a cast error when using the same code on float columns: 对于整数列,以下代码可以正常工作,但在float列上使用相同的代码时会出现转换错误:

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

For float columns I'm using the following code but it's slow. 对于浮动列我使用以下代码,但速度很慢。

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

I have 8 integer columns and 9 float columns and the behavior has been consistent across all columns so that's why I think it's an issue with the column type. 我有8个整数列和9个浮点列,并且所有列的行为都是一致的,这就是为什么我认为这是列类型的问题。 But I'm new to F# and don't know anything so I'm hoping you can help me. 但我是F#的新手并且什么都不知道,所以我希望你能帮助我。

Thank you for taking the time to help, it's much appreciated. 感谢您抽出宝贵时间提供帮助,非常感谢。

SQLProvider version: 1.0.41 SQLProvider版本:1.0.41

System.Data.SQLite.Core version: 1.0.104 System.Data.SQLite.Core版本:1.0.104

The error is: System.InvalidCastException occurred in FSharp.Core.dll 错误是:FSharp.Core.dll中发生System.InvalidCastException

Added Information 添加信息

I created a new table with one column of type float. 我用一个float类型的列创建了一个新表。 I inserted the values 2.2 and 4.2. 我插入了值2.2和4.2。 Using SQLProvider and System.Data.SQLite.Core I connected queried the database using minBy or maxBy and I get the cast exception. 使用SQLProvider和System.Data.SQLite.Core我连接使用minBy或maxBy查询数据库,我得到强制转换异常。 If the column type is integer it works correctly. 如果列类型是整数,则它可以正常工作。

More Added Information 更多新增信息

Exception detail: 例外细节:

System.Exception was unhandled Message: An unhandled exception of type 'System.Exception' occurred in >FSharp.Core.dll Additional information: Unsupported execution expression value(FSharp.Data.Sql.Runtime.QueryImplementation+SqlQueryable 1[FSharp.>Data.Sql.Common.SqlEntity]).Min(row => >Convert(Convert(row.GetColumn("X"))))` System.Exception未处理消息:> FSharp.Core.dll中发生未处理的类型'System.Exception'的异常附加信息:不支持的执行表达式value(FSharp.Data.Sql.Runtime.QueryImplementation+SqlQueryable 1 [FSharp。> Data .Sql.Common.SqlEntity])。Min(row = >> Convert(Convert(row.GetColumn(“X”))))`

Code that fails: 代码失败:

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

Update 2/1/17 更新2/1/17

Another user was able to reproduce the issue so I filed an Issue with SQLProvider. 另一位用户能够重现该问题,因此我向SQLProvider提交了一个问题。 I'm now looking at workarounds and while the following code works and is fast, I know there's a better way to do it - I just can't find the correct way. 我现在正在寻找变通方法,虽然以下代码工作且速度很快,但我知道有更好的方法 - 我找不到正确的方法。 If somebody answers with better code I'll accept that answer. 如果有人用更好的代码回答,我会接受这个答案。 Thanks again for all the help. 再次感谢所有的帮助。

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

This is my workaround that @s952163 and good people in the SO f# chat room helped me with. 这是我的解决方法,@ s952163和SO f#聊天室的好人帮助了我。 Thanks again to everyone who helped. 再次感谢所有帮助过的人。

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

You need to coerce the output column to int or float (whichever you need or is giving trouble to you). 您需要将输出列强制转换为intfloat (无论您需要还是给您带来麻烦)。 You also need to take care in case any of your columns are nullable. 如果您的任何列都可以为空,您还需要注意。 The example below will coerce the column to float first (to take care of being nullable), then convert it to int , and finally get the minimum: 下面的示例将强制列首先float (以便可以为空),然后将其转换为int ,最后得到最小值:

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

You might want to change the order of course, or just say float Mycolumn . 您可能想要更改当然的顺序,或者只是说float Mycolumn

Update: With Sqlite it indeed causes an error. 更新:使用Sqlite确实会导致错误。 You might want to do query { ... } |> Seq.minBy to extract the smallest number. 您可能想要query { ... } |> Seq.minBy来提取最小的数字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM