sql-server - 向投影添加更多子查询时 SQL 语句嵌套太深
问题描述
复制项目在 github 上可用,使用AdventureWorks2016
数据库。GitHub 复制
我们有自定义过滤机制来满足我们的需求。它的作用是 - 它获取输入数据,使用完整查询构建表达式树并将其传递EntityFramework
给执行。我们有两个部分的查询——获取基本实体和获取一些额外的数据值,在最终投影中表示为子查询。
问题:
当获得超过 20 个子查询时,SqlServer
会引发错误:
您的 SQL 语句的某些部分嵌套得太深。重写查询或将其分解为更小的查询。
经过仔细调查,结果发现与此类似的查询:
var products = db.Products.Where(p => productIds.Contains(p.ProductID))
.Select(p => new
{
Entity = p,
Extras = new
{
TotalTransactions = p.TransactionHistories.Count(),
TotalCostChanges = p.ProductCostHistories.Count(),
AverageTransactionCost = p.TransactionHistories.Average(t => t.Quantity * t.ActualCost),
MaxQuantity = (int?)p.TransactionHistories.Max(t => t.Quantity)
}
});
导致生成如下 SQL 查询:
SELECT
[Project3].[ProductID] AS [ProductID],
[Project3].[Name] AS [Name],
[Project3].[C1] AS [C1],
[Project3].[C2] AS [C2],
[Project3].[C3] AS [C3],
(SELECT
MAX([Extent5].[Quantity]) AS [A1]
FROM [Production].[TransactionHistory] AS [Extent5]
WHERE [Project3].[ProductID] = [Extent5].[ProductID]) AS [C4]
FROM ( SELECT
[Project2].[ProductID] AS [ProductID],
[Project2].[Name] AS [Name],
[Project2].[C1] AS [C1],
[Project2].[C2] AS [C2],
(SELECT
AVG([Filter4].[A1]) AS [A1]
FROM ( SELECT
CAST( [Extent4].[Quantity] AS decimal(19,0)) * [Extent4].[ActualCost] AS [A1]
FROM [Production].[TransactionHistory] AS [Extent4]
WHERE [Project2].[ProductID] = [Extent4].[ProductID]
) AS [Filter4]) AS [C3]
FROM ( SELECT
[Project1].[ProductID] AS [ProductID],
[Project1].[Name] AS [Name],
[Project1].[C1] AS [C1],
(SELECT
COUNT(1) AS [A1]
FROM [Production].[ProductCostHistory] AS [Extent3]
WHERE [Project1].[ProductID] = [Extent3].[ProductID]) AS [C2]
FROM ( SELECT
[Extent1].[ProductID] AS [ProductID],
[Extent1].[Name] AS [Name],
(SELECT
COUNT(1) AS [A1]
FROM [Production].[TransactionHistory] AS [Extent2]
WHERE [Extent1].[ProductID] = [Extent2].[ProductID]) AS [C1]
FROM [Production].[Product] AS [Extent1]
WHERE [Extent1].[ProductID] IN (707, 708, 709, 711)
) AS [Project1]
) AS [Project2]
) AS [Project3]
将每个属性添加到 Extras 后,就会再创建一个嵌套查询。
有什么方法EntityFramework
可以生成更好的查询(请参阅:所有那些对值 C1、C2... 的嵌套查询都可以表示为主选择中的简单子查询)或者应该以某种完全不同的方式创建这种查询?
解决方案
推荐阅读
- python - 如何在 Odoo 12 的看板视图模板中直接访问 python 方法?
- signature - 多个 MAIN 签名
- python - 如何在 Python 中链接文件对象?
- java - 我收到错误我在线程“main”java中收到错误异常...下面的完整错误
- sql - 如何从数据库表中显示重复的电子邮件计数?
- java - 摆脱 IntelliJ 中没有大括号的简单语句的格式警告
- javascript - 如何在不使用节点请求下载响应内容的情况下发送 GET 请求?
- ruby-on-rails - 将表单文本输入中的电子邮件列表保存到模型 email_list 属性(数组)中
- systemd - 为什么 dbus-daemon 需要 1 分钟 30 秒才能启动?
- c# - VS Code 2017 - C# 错误 - “某些项目无法加载。请查看输出以获取更多详细信息”