F# query concatenation

爱⌒轻易说出口 提交于 2019-12-14 01:36:27

问题


I am using SqlDataConnection data provider in F# to migrate some rows, part of that migration is to make a join between 3 tables like this, think of it as an inheritance of tables A, B, C where B and C inherit from A so the thing is I need to get is (in Linq-like):

        Bs.Join(As, b.PK, a.FK).Select(new {...})
.Concat(Cs.Join(As, c.PK, a.FK).Select(new {...})

In F#, the closest I got to this was:

 let result = seq {
     yield! query { ... }
     yield! query { ... }
 }

but I've been told this will produce 2 SQL queries and the overall result will be on-memory. The question being: is there a way to make this "concatenation" as a query computation expression without using seq so that all happens in a single SQL query?


回答1:


Here's some example code that combines two queries using SQL UNION or UNION ALL.

First, the setup. Note that I've added logging to dbContext so you can see what happens behind the scenes.

#r "System.Data.dll"
#r "System.Data.Linq.dll"
#r "FSharp.Data.TypeProviders.dll"

open System
open System.Linq
open Microsoft.FSharp.Data.TypeProviders

type sql = SqlDataConnection<connStr>

let createDbContext() = 
    let dbContext = sql.GetDataContext()
    // add logging to console
    dbContext.DataContext.Log <- System.Console.Out 
    dbContext 

let db = createDbContext()
let products = db.Product

let q1 = query { for x in products do select x }
let q2 = query { for y in products do select y }

The Union extension method combines queries as one query using UNION

let qUnion = q1.Union(q2)
qUnion.ToList() |> Seq.toList

Here's the logged output:

SELECT [t2].[Id], [t2].[Name]
FROM (
    SELECT [t0].[Id], [t0].[Name]
    FROM [dbo].[Product] AS [t0]
    UNION
    SELECT [t1].[Id], [t1].[Name]
    FROM [dbo].[Product] AS [t1]
    ) AS [t2]

The Concat extension method combines queries as one query using UNION ALL

let qConcat = q1.Concat(q2)
qConcat.ToList() |> Seq.toList

Here's the logged output:

SELECT [t2].[Id], [t2].[Name]
FROM (
    SELECT [t0].[Id], [t0].[Name]
    FROM [dbo].[Product] AS [t0]
    UNION ALL
    SELECT [t1].[Id], [t1].[Name]
    FROM [dbo].[Product] AS [t1]
    ) AS [t2]

There's no special syntax for unions in query expressions, AFAIK.



来源:https://stackoverflow.com/questions/33178027/f-query-concatenation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!