请帮我为下面的SQL查询写LINQ语句

时间:2019-02-13 21:53:55

标签: c# linq

名为MyDB的My Db有5个表:MSize,MModel,Met,MResult,SResult。它们的连接如下:

MSize与MModel有一个公共字段MSizeId。

MModel与具有MModelId的Met链接。

Met可以基于MId与MResult链接。

类似地,SResult可以与SResultId上的MResult链接。

我的目标是获得所有项(Msize表中的描述字段)的Acc(十进制数据类型)> = 70和<= 130(按描述分组)的平均准确性。

这是我的SQL查询:

use MyDB;
SELECT a.[Description],AVG(CASE WHEN d.[Acc] >= 70 AND d.[Acc] <= 130 THEN d.[Acc] END)
  FROM MSize a 
  INNER JOIN MModel b   ON a.MSizeId = b.MSizeId
  INNER JOIN Met c      ON b.MModelId = c.MModelId
  INNER JOIN MResult d  ON c.MId = d.MId
  INNER JOIN SResult e  ON d.SResultId = e.SResultId
  GROUP BY a.Description

此查询为我在SQL Server上提供了正确的结果。

我一直在努力编写相同的LINQ查询。问题来自于SQL CASE语句。我不想指定CASE的错误结果,这意味着,如果d.acc不在SQL查询中指定的范围内,则将其丢弃。

假定所有Model类和字段都与这些DBtables和列具有相同的名称。给定SQL语句的LINQ查询是什么?

您可以在大括号中填写代码:

using (var db = new MyDBContext()){ }

此处MyDBContext指的是LINQ生成的局部类数据模型模板

1 个答案:

答案 0 :(得分:0)

您不必费心编写这些类,我也不会为您这样做。

显然,您有一个MSizes序列,其中每个Msize都有零个或多个MModel。每个MModel都有零个或多个Mets,每个Met都有零个或多个MResult,每个MResult都有一个Acc。

您还忘了用文字写下您的要求,现在我不得不从您的SQL查询中提取它

似乎您希望每个MSize的描述都具有其所有Acc的平均值,其值在70到130之间。

如果使用实体框架,则可以使用virtual ICollection,它使工作变得相当容易。我将分两个步骤进行操作,因为下面我对GroupJoin进行了相同的操作,而没有使用ICollection。两种方法的第二部分是相同的。

首先,我将获取每个MSize的描述以及该MSize的MModel的Mets的MResult中所有更深的Acc:

var descriptionsWithTheirAccs = dbContext.MSizes.Select(msize => new
{
    Description = msize.Description,

    // SelectMany the inner collections until you see the Accs
    Accs = mSize.Mmodels.SelectMany(

        // collection selector:
        model => model.Mets,

        // result selector: flatten MResults in the Mets
        (model, mets) => mets
            .SelectMany(met => met.MResults,

            // result Selector: from every mResult take the Acc
            (met, mResults) => mResults
                  .Select(mResult => mResult.Acc)));

现在,我们有了每个MSize的描述,以及其中包含的所有Acc, 我们可以丢弃所有我们不需要的Accs,然后平均剩余的Accs:

var result= descriptionsWithTheirAccs.Select(descriptionWithItsAccs => new
{
    Description = descriptionWithItsAccs.Description,

    Average = descriptionWithItsAccs.Accs
        .Where(acc => 70 <= acc && acc <= 130)
        // and the average from all remaining Accs
        .Avg(),
});

如果您无权访问ICollection,则必须自己进行Groupjoin,如果您有很多表,这看起来就很可怕:

var descriptionsWithTheirAccs = dbContext.MSizes.GroupJoin(dbContext.MModels,
    msize => msize.MSizeId,
    mmodel => mmodel.MSizeId,
    (msize, mmodels) => new
    {
        Description = msize.Description,

        Accs = mmodels.GroupJoin(dbContext.Mets,
            mmodel => mModel.MModelId,
            met => met.MModelId,
            (mmodel, metsofThisModel) => metsOfThisModel
                .GroupJoin(dbContext.MResults,
                met => met.MetId
                mresult => mresult.MetId,

                // result selector
                (met, mresults) => mResult.Select(mresult => mresult.Acc))),
      });

现在您有了DescriptionsWithTheirAccs,则可以使用上面的Select计算平均值。