【问题标题】:Select one of each group by date using entity framework使用实体框架按日期选择每个组之一
【发布时间】:2021-07-19 08:51:17
【问题描述】:
I have a table like this 
+----+----------+------------+
| se | FKMember |  Expdate   |
+----+----------+------------+
|  0 |     1    | 2019-03-01 |
|  1 |     3    | 2019-03-07 |
|  2 |     2    | 2019-01-01 |
|  3 |     1    | 2019-04-01 |
|  4 |     3    | 2019-09-07 |
|  5 |     1    | 2019-05-01 |
+----+-----------------------+

我想返回一行,这一行包含会员的最大日期

我需要的结果应该是

+----+----------+------------+
| s. | FKMember |  Expdate   |
+----+----------+------------+
|  2 |     2    | 2019-01-01 |
|  4 |     3    | 2019-09-07 |
|  5 |     1    | 2019-05-01 |
+----+-----------------------+

我使用此代码,但它返回一行,此行包含最大日期 我应该怎么做才能让每个成员排成一行 ..................................................... ..................................................... ................................................

private void R2()
     
         int? MemberIDAsInt = string.IsNullOrEmpty(MemberID) ? null : (int?)Convert.ToInt32(MemberID);
         int? MainPackageCodeAsInt = string.IsNullOrEmpty(MainPackageCode) ? null : (int?)Convert.ToInt32(MainPackageCode);
         int? SubPackageCodeAsInt = string.IsNullOrEmpty(SubPackageCode) ? null : (int?)Convert.ToInt32(SubPackageCode);
         int? PackageTypeCodeAsInt = string.IsNullOrEmpty(PackageTypeCode) ? null : (int?)Convert.ToInt32(PackageTypeCode);
         int? PackageCodeAsInt = string.IsNullOrEmpty(PackageCode) ? null : (int?)Convert.ToInt32(PackageCode);
         int? CorporateCodeAsInt = string.IsNullOrEmpty(CorporateCode) ? null : (int?)Convert.ToInt32(CorporateCode);
         int? SalesCodeAsInt = string.IsNullOrEmpty(SalesCode) ? null : (int?)Convert.ToInt32(SalesCode);
         int? TrainerCodeAsInt = string.IsNullOrEmpty(TrainerCode) ? null : (int?)Convert.ToInt32(TrainerCode);
         int? RelationshipCodeAsInt = string.IsNullOrEmpty(RelationshipCode) ? null : (int?)Convert.ToInt32(RelationshipCode);
         int? NationalityCodeAsInt = string.IsNullOrEmpty(NationalityCode) ? null : (int?)Convert.ToInt32(NationalityCode);
         bool? GenderAsBool = string.IsNullOrEmpty(Gender.ToString()) ? null : (bool?)Convert.ToBoolean(Gender);
         DateTime? StartDatePackageFromAsDate = StartDatePackageFrom == string.Empty ? null : (DateTime?)Convert.ToDateTime(StartDatePackageFrom);
         DateTime? StartDatePackageToAsDate = StartDatePackageTo == string.Empty ? null : (DateTime?)Convert.ToDateTime(StartDatePackageTo);
         DateTime? EndDatePackageFromAsDate = EndDatePackageFrom == string.Empty ? null : (DateTime?)Convert.ToDateTime(EndDatePackageFrom);
         DateTime? EndDatePackageToAsDate = EndDatePackageTo == string.Empty ? null : (DateTime?)Convert.ToDateTime(EndDatePackageTo);

         using (var dbcontext = new database.GymEntities())
         {
             var Employee_Data = dbcontext
                              .VPackageForMembers

                              .Where(u => (MemberIDAsInt == null) ? true : u.FKMemberID == MemberIDAsInt)
                              .Where(u => (MainPackageCodeAsInt == null) ? true : u.FKMainPakage == MainPackageCodeAsInt)
                              .Where(u => (SubPackageCodeAsInt == null) ? true : u.FKSubPackage == SubPackageCodeAsInt)
                              .Where(u => (PackageTypeCodeAsInt == null) ? true : u.FKPackageType == PackageTypeCodeAsInt)
                              .Where(u => (PackageCodeAsInt == null) ? true : u.FKPackage == PackageCodeAsInt)
                              .Where(u => (CorporateCodeAsInt == null) ? true : u.FKCorporate == CorporateCodeAsInt)
                              .Where(u => (SalesCodeAsInt == null) ? true : u.FKSalesPerson == SalesCodeAsInt)
                              .Where(u => (TrainerCodeAsInt == null) ? true : u.FKTrainer == TrainerCodeAsInt)
                              .Where(u => (RelationshipCodeAsInt == null) ? true : u.FKRelationShip == RelationshipCodeAsInt)
                              .Where(u => (NationalityCodeAsInt == null) ? true : u.FKRelationShip == NationalityCodeAsInt)
                              .Where(u => (GenderAsBool == null) ? true : u.Gender == GenderAsBool)
                              .Where(u => (StartDatePackageFromAsDate == null) ? true : u.StartDate >= StartDatePackageFromAsDate && u.StartDate <= StartDatePackageToAsDate)
                              .Where(u => (EndDatePackageFromAsDate == null) ? true : u.ExpDate >= EndDatePackageFromAsDate && u.ExpDate <= EndDatePackageToAsDate)
                              .OrderByDescending (u=> u.ExpDate)
                              .Take(1)
                              .Select(u => new
                              {
                                  
                                  u.FKMemberID,
                                  u.MemberEnglishName,
                                  u.MainPackageEnglishName,
                                  u.SubPackageEnglishName,
                                  u.PackageTypeEnglishName,
                                  u.PackageEnglishName,
                                  u.ExpDate,
                                  u.PhoneNo1
                              }
                              )                                
                              .ToList();

             datasource = new ReportDataSource("MemberExpireData", Employee_Data);
         }
     }

【问题讨论】:

  • 看看一些关于使用 LINQ 进行分组的教程可能是个好主意。他们可能会有所帮助。
  • 这能回答你的问题吗? Entity Framework Group By with Max Date and count ALSO 不要使用 Where like this。 EF 非常愚蠢,当 SQL Server 构建执行计划时,所有这些条件都会降低您的性能。全部为 NULL 时的事件。
  • 我需要允许用户选择条件如何以更好的方式重构它??? @eocron

标签: c# entity-framework


【解决方案1】:

重构 Where 条件:

using (var dbcontext = new database.GymEntities())
{
    var query = dbcontext.VPackageForMembers.AsQueryable();
    if (memberIDAsInt.HasValue)
        query = query.Where(u => u.FKMemberID == memberIDAsInt);
    if (mainPackageCodeAsInt.HasValue)
        query = query.Where(u => u.FKMainPackage == mainPackageCodeAsInt);
    // ...

    var employeeData = query.OrderByDescending(u=> u.ExpDate)
        .Take(1)
        .Select(u => new
        {
            u.FKMemberID,
            u.MemberEnglishName,
            u.MainPackageEnglishName,
            u.SubPackageEnglishName,
            u.PackageTypeEnglishName,
            u.PackageEnglishName,
            u.ExpDate,
            u.PhoneNo1
        }).ToList();
    datasource = new ReportDataSource("MemberExpireData", employeeData);
}

通过在代码中进行比较,您可以将生成的 SQL 简化为仅包含实际需要提供的条件。

接下来,按FK进行分组:

    var employeeData = query
        .Select(g => new
        {
            u.FKMemberID,
            u.MemberEnglishName,
            u.MainPackageEnglishName,
            u.SubPackageEnglishName,
            u.PackageTypeEnglishName,
            u.PackageEnglishName,
            u.ExpDate,
            u.PhoneNo1
        }).GroupBy(u => u.FKMemberID)
        .Select(g => g.OrderByDescending(u => u.ExpDate).FirstOrDefault())
        .ToList();

前提是投影您的结果 /w 选择并按所需值分组,在您的情况下为 FKMemberID。然后,您可以从组中对结果进行排序并选择第一个值。请注意,在Select 表达式中,您需要使用FirstOrDefault 而不是FirstFirst 会导致 Linq 生成错误,但它似乎应该可以工作,因为每个组应该至少包含 1 个条目。

如果您的整体数据量会随着时间的推移而增长,您还应该考虑添加分页,因为这样的搜索最终可能会返回大量 #s 的结果。

【讨论】:

    猜你喜欢
    • 2013-04-22
    • 1970-01-01
    • 2019-05-11
    • 1970-01-01
    • 2021-09-24
    • 1970-01-01
    • 2013-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多