在 .NET Core 中运行多个 sql 查询以获取矩阵结果
Posted
技术标签:
【中文标题】在 .NET Core 中运行多个 sql 查询以获取矩阵结果【英文标题】:Running multiple sql queries to get matrix results in .NET Core 【发布时间】:2020-10-19 11:20:42 【问题描述】:我正在尝试从数据库中获取结果以生成某种矩阵结果以发送回前端。关键是我有 X 轴和 Y 轴的百分位值,我将其分成 10 个部分以获得 10x10 表。为了获得每个值,我计算不同的用户 ID,所以它类似于 1-1、1-2 ... 10-10。
这是我目前想要改进的代码(虽然尚未完成,只是我目前的想法),因为一个接一个地运行 100 个查询似乎不是一个好的解决方案。但是,我有点卡住如何使性能更好,以及是否应该在长度为 100 的字典或多维矩阵数组中返回结果以使其成为良好的实践代码。提前感谢任何人的提示,我的代码如下:
public async Task GenerateMatrix(List<double> x, string xAxis, List<double> y, string yAxis, Parameters parameters)
IDictionary<string, string> xDict = GenerateRanges(x, parameters.XAxis);
IDictionary<string, string> yDict = GenerateRanges(y, parameters.YAxis);
var innerJoin = GenerateInnerJoin(parameters);
var whereClauses = GenerateWhereClause(parameters);
var sql = $@"SELECT COUNT(DISTINCT [dbo].[nameof(Table)].[nameof(Table.UserId)]) FROM [dbo].[nameof(Table)] innerJoin ";
if (whereClauses.Any())
sql += " WHERE " + string.Join(" AND ", whereClauses);
for (int i = 0; i < x.Count; i++)
var queryToExecute = "";
for (int j = 0; j < y.Count; j++)
queryToExecute = sql + " AND " + xDict.Values.ElementAt(i) + " AND " + yDict.Values.ElementAt(j);
var userCount = await Store().QueryScalar<int>(queryToExecute);
return null;
private IDictionary<string, string> GenerateRanges(List<double> axis, string columnTitle)
IDictionary<string, string> d = new Dictionary<string, string>();
for (int i = 0; i < axis.Count; i++)
var rangeSql = $@" [dbo].[nameof(Table)].[columnTitle]";
if (i == 0)
d.Add(axis[i].ToString(), rangeSql + " < " + axis[i]);
else if (i == axis.Count - 1)
d.Add(axis[i] + "+", rangeSql + " > " + axis[i]);
else
d.Add(axis[i-1] + "-" + axis[i], rangeSql + " > " + axis[i-1] + " AND " + rangeSql + " < " + axis[i]);
return d;
sql 看起来像这样:
SELECT
COUNT(DISTINCT [dbo].[Table].[UserId])
FROM [Table]
WHERE Table.[ClientId] = '2'
AND [dbo].[Table].[ProbabilityAlive] < 0.1
AND [dbo].[Table].[SpendAverage] < 24.86
所以会有 10000 行这样的行。
ProbabilityAlive
和 SpendAverage
是来自前端的列标题,可能还有其他列标题。
对于这两列,我计算百分位值,然后我将其分成十部分,一个是 X 轴,另一个是 Y 轴。然后我使用上面的 sql 查询来获取每个矩阵值的值,因为矩阵是 10x10,所以它变成了 100 个查询。
因此,我想获得 100 个整数值,我仍在试图弄清楚是否最好将数据放入字典中,然后将具有范围 xy 和值的键作为选择结果(例如 "0-1", 5472"
),或者是否把它放在多维数组或其他东西中。我有xDict
,其中包含范围作为键,例如“0-1”,然后是 sql 语句 ProbabilityAlive > 0 AND ProbabilityALive yDict 为 Y 轴添加相同的值。然后我有两个列表 x
和 y
包含 10 个用于这些范围的双精度值
【问题讨论】:
这是一个 100% 的 SQL 问题,但缺少实际的 SQL 查询。用样本数据和结果解释你真正想做的事情。也许您所需要的只是GROUP BY
子句中的WITH ROLLUP
表达式
是的@AndrewMorton
您尚未解释数据的外观或您的期望。该代码根本没有帮助。只有第一段和查询是相关的,但它们似乎不相关。什么百分位? T-SQL 具有像PERCENTILE_DISC 这样的百分位函数,可用于连续返回各种百分位。您可以创建一个返回 100 行的查询,其中包含您想要的 X、Y 和百分位数数据,但是您想要什么 do? X 和 Y 值从何而来?
您是否尝试为ProbabilityAlive
和ProbabilityAlive
字段生成存储桶并为每个组合生成唯一客户的百分位数(或百分比?)?
并非如此。你描述的是代码,而不是你真正想要得到的输出,数据是什么样的,以及期望的输出是什么
【参考方案1】:
您似乎想要计算 ProbabilityAlive
和 SpendAverage
的特定范围内的用户数。
首先,您需要生成范围组合。在 SQL 中生成组合的简单方法是连接两个表或一组值。
如果您有两个表,其范围值如下:
create table ProbabilityRanges
(
LowBound decimal(3,2), UpperBound(3,2)
)
create table SpendRanges
(
LowBound decimal(3,2), UpperBound(3,2)
)
您可以使用交叉连接来生成所有组合:
SELECT
SpendRanges.LowBound as SLow,
SpendRanges.UpperBound as SUpper,
ProbabilityRangers.LowBound as PLow,
ProbabilityRanges.UpperBound as PUpper
FROM ProbabilityRanges CROSS JOIN SpeedRanges
您可以使用这些组合来过滤和计算另一个表中在这些范围内的行:
SELECT
SpendRanges.LowBound as SpendValue,
SpendRanges.LowBound as ProbabilityValue,
Count(DISTINCT UserID) as Count
FROM SomeTable CROSS JOIN ProbabilityRanges CROSS JOIN SpeedRanges
Where
SomeTable.ClientID=2
AND SomeTable.SpendAverage >=SpeedRanges.LowBound
AND SpendAverage < SpeedRanges.UpperBound
AND SomeTable.ProbabilityAlive >= ProbabilityRangers.LowBound
AND SomeTable.ProbabilityAlive < ProbabilityRanges.UpperBound
GROUP BY SpendRanges.LowBound,SpendRanges.LowBound
可以为特定数量的箱动态创建边界,例如使用数字表。你必须提供更多关于你真正想要的信息
【讨论】:
【参考方案2】:只有两个维度,最容易做和维护,就是制作一个 TSQL 存储过程,输出你想要的元组(默认输出)。 将您从前端获得的输入作为参数传入。
如果您通过返回 JSON(或 XML)的 Web 服务 HTTP GET 获得该功能会怎样? 改用 TSQL 模拟它。
由于您可以直接访问 SQL Server,因此您调用“get”类型的存储过程并传递参数,并获得元组结果。 独立于您的 .Net 核心应用程序,易于编写和测试。也会很快。
type "get" = 只是一个只读 SP,我将我的命名为 USP_GET_method_name。 我还使用 SP 来保存 SQL 端验证,所以我称它们为 USP_PUT_method_name。
干杯
【讨论】:
这不能回答问题。也没有理由创建存储过程 - 它不会更改查询的执行方式或返回的内容。存储过程可用于将复杂代码从应用程序移至查询,但不会改变查询的实际作用 将 HTTP 和 HTTP 动词与数据库混合起来根本没有帮助 我很不同意,TSQL 比在 .Net 中循环更擅长将矩阵式输出直接渲染为元组以供 .Net 使用。命名约定以区分与前端相关的 SP,与纯后端相关的 SP。 FWIW,这与我们对 SSIS(使用 SP)所做的非常相似。 您没有回答问题。您刚刚描述了您的自定义命名约定。 SSIS 与 html 或执行分析查询无关,它是一个 ETL 工具 实际上想发表评论而不是答案,但我还没有足够的声誉以上是关于在 .NET Core 中运行多个 sql 查询以获取矩阵结果的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core,以查询字符串为模板的 Web API RouteAttribute
如何在 asp.net core 中编写一个高性能的 sql 查询应用程序?
通过 ASP.NET Core Web API 使用存储过程从 SQL Server 返回多个行集
在 ASP.NET MVC 中向控制器传递多个参数;此外,在 LINQ-to-SQL 中生成动态查询
编码 ASP.NET Core 和 SQL Server 的问题
OUTPUT INSERTED Id/SCOPE_IDENTITY() 在 C# (ASP.NET Core Razor Pages) SQL 查询中返回 null,在 SQL Server Mana