我正在撰写一份注定要成为Azure功能的销售报告。使用FSharp.Data.TypeProviders.SqlDataConnection进行数据访问我在尝试解析产品的父部门时获得System.NotSupportedException: An IQueryable that returns a self-referencing Constant expression is not supported.
。
脚本看起来像这样:
#r "System.Data.dll"
#r "FSharp.Data.TypeProviders.dll"
#r "System.Data.Entity.dll"
#r "System.Data.Linq.dll"
open System
open Microsoft.FSharp.Data
open Microsoft.FSharp.Data.TypeProviders
open System.Linq
open System.Data.Linq
open System.Data.Entity
type DbConn = SqlDataConnection< @"super secrete connection string here">
type SubSelOut = { ``Department Name``: String;
``Parent Id``: Nullable<int>;
``Product Id``: int }
[< CLIMutable >]
type QueryGrouping = {``Product Id``: Nullable<int>;
``Product SKU``: string;
Price: Decimal;
``Department Name``: string;
``Parent Department Name``: string; }
type SkuOut = { sku: string;
``Product ID``: Nullable<int>;
``Product Name``: string;
Category: string;
``Sub-Category``: string; }
let db = DbConn.GetDataContext()
let p2dQuery =
query { for p in db.Products do
groupJoin p2d in db.Prods_to_depts
on ( p.Id = p2d.Product_id.Value ) into pd
groupJoin dep in db.Departments
on ( pd.Select(fun e -> e.Dept_id.Value).FirstOrDefault() = dep.Id ) into d
where ( pd.FirstOrDefault().Is_main )
select ( { ``Department Name`` = d.Select( fun e -> e.Name).First();
``Parent Id`` = d.Max( fun e -> e.Parent_id );
``Product Id`` = p.Id }) }
query { for oi in db.Order_items do
join prod in db.Products
on ( oi.Product_id.Value = prod.Product_id )
join pdt in p2dQuery
on ( prod.Product_id = pdt.``Product Id`` )
join pd in db.Departments
on ( pdt.``Parent Id``.Value = pd.Id )
groupBy ( { ``Product Id`` = oi.Product_id;
``Product SKU`` = oi.Product_sku;
Price = prod.Price;
``Department Name`` = pdt.``Department Name``;
``Parent Department Name`` = pd.Name; } ) into gt
select ( { sku = gt.Key.``Product SKU``;
``Product ID`` = gt.Key.``Product Id``;
``Product Name`` = gt.Select( fun (oi,_,_,_) -> oi.Product_name ).FirstOrDefault();
Category = gt.Select( fun (_,_,_,pd) -> pd.Name ).FirstOrDefault();
``Sub-Category`` = gt.Select( fun (_,_,d,_) -> d.``Department Name`` ).FirstOrDefault(); } ) }
|> Seq.toList
可以用以下方法复制相关的数据结构:
CREATE TABLE [dbo].[products](
[id] [int] IDENTITY(1000,1) NOT NULL PRIMARY KEY,
[sku] [nvarchar](300) NULL,
[name] [nvarchar](500) NULL,
[price] [decimal] NOT NULL
--additional product props
);
CREATE TABLE [dbo].[departments](
[id] [int] IDENTITY(1000,1) NOT NULL PRIMARY KEY,
[name] [varchar](200) NULL,
[parent_id] [int] NULL
--additional department props
);
CREATE TABLE [dbo].[products_to_deptartments](
[id] [int] IDENTITY(10000,1) NOT NULL PRIMARY KEY,
[department_id] [int] NULL,
[product_id] [int] NULL,
[is_main] [bit] NOT NULL );
CREATE TABLE [dbo].[order_items](
[id] [int] IDENTITY(1000,1) NOT NULL PRIMARY KEY,
[order_id] [nvarchar](50) NULL,
[product_id] [int] NULL,
[product_sku] [nvarchar](50) NULL,
[product_name] [nvarchar](500) NULL,
[price] [decimal] NOT NULL,
[quantity] [int] NOT NULL
--additional order item info
);
GO
我尝试克隆的SQL查询是这样的:
SELECT
--agragate data here
department_table.department_name,
parent_department.department_name AS parent_name
FROM order_items
LEFT OUTER JOIN products
ON products.id = order_items.product_id
LEFT OUTER JOIN ( SELECT
MAX(departments.department_name) AS department_name,
MAX(departments.parent_id) AS parent_id,
products.id
FROM products
INNER JOIN products_to_deptartments
ON products.id = products_to_deptartments.product_id
INNER JOIN departments
ON products_to_deptartments.dept_id = departments.id
WHERE products_to_deptartments.is_main = 1
GROUP BY products.id ) AS department_table
ON products.id = department_table.product_id
LEFT OUTER JOIN departments parent_department
ON parent_department.id = department_table.parent_id
GROUP BY
order_items.id,
order_items.sku,
products.price,
department_table.name,
parent_department.name
ORDER BY order_items.product_sku;
GO