F# 查询:查找每组中具有最大值的行

F# query: find rows with max value in each group

在我的项目中我使用:

我有一个与此类似的问题:SQL select only rows with max value on a column,但我想知道如何使用 F# 查询工作流表达该问题中出现的 SQL:

SELECT a.id, a.rev, a.contents
FROM YourTable a
INNER JOIN (
    SELECT id, MAX(rev) rev
    FROM YourTable
    GROUP BY id
) b ON a.id = b.id AND a.rev = b.rev

直接翻译

对于直接翻译,内部查询是:

let innerQuery =
    query {
        for inner in ctx.YourTable do
        groupBy inner.id into grp
        select (grp.Key, grp.Max(fun ent -> ent.rev))
    }

然后,理论上,我认为完整的查询应该是:

query {
    for outer in ctx.YourTable do
    join inner in innerQuery
        on ((outer.id, outer.rev) = inner)
    select outer
}

但是,这不起作用:

Type mismatch when building 'ty': function type doesn't match delegate type. Expected

'Microsoft.FSharp.Core.FSharpFunc`2[Program+YourTable,System.Tuple`2[System.Int32,System.Int32]]'

, but received type

'Microsoft.FSharp.Core.FSharpFunc`2[Program+YourTable,Microsoft.FSharp.Linq.RuntimeHelpers.AnonymousObject`2[System.Int32,System.Int32]]'.

我可能是错的,也可能是 bug/limitation。也许有人有解决方法。

替代翻译

但是,如果您接受略有不同的翻译,它确实有效:

query {
    for outer in ctx.YourTable do
    where (
        query {
            for inner in ctx.YourTable do
            groupBy inner.id into grp
            exists (grp.Key = outer.id && grp.Max(fun ent -> ent.rev) = outer.rev)
        })
    select outer
}

生成的SQL为:

SELECT [y].[id], [y].[rev], [y].[contents]
FROM [YourTable] AS [y]
WHERE EXISTS (
    SELECT 1
    FROM [YourTable] AS [y0]
    GROUP BY [y0].[id]
    HAVING ([y0].[id] = [y].[id]) AND (MAX([y0].[rev]) = [y].[rev]))

输出为:

{ id = 2
  rev = 1
  contents = "..." }
{ id = 1
  rev = 3
  contents = "..." }

请注意,我在构建模型时必须设置 id, rev 的复合主键:

override __.OnModelCreating(modelBuilder: ModelBuilder) =
    modelBuilder.Entity<YourTable>()
        .HasKey([| "id"; "rev" |]) |> ignore

完整代码是 here.