首页 > 解决方案 > 在 .NET Core 中运行多个 sql 查询以获取矩阵结果

问题描述

我正在尝试从数据库中获取结果以生成某种矩阵结果以发送回前端。关键是我有 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 <1,然后为 Y 轴从yDict. 然后我有两个列表xy其中包含 10 个用于这些范围的双精度值

标签: c#sqltsqlasp.net-core.net-core

解决方案


看起来您想要计算 和 的特定范围的用户ProbabilityAliveSpendAverage

首先,您需要生成范围组合。在 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

可以为特定数量的 bin 动态创建边界,例如使用 Numbers 表。你必须提供更多关于你真正想要的信息


推荐阅读