【问题标题】:LINQ get a record with max date from multiple joinsLINQ 从多个连接中获取具有最大日期的记录
【发布时间】:2017-10-30 18:11:58
【问题描述】:

我有三个表:Course、CourseLocations、CourseSchedules

每门课程可以在一个或多个地点举办(一对多) 每个位置可以托管一个或多个时间表(一对多)

我需要获取所有具有 Schedules.Date> Today 的课程,唯一名称,并显示包含在表 CourseSchedules 中的日期的 MAX 值

我当前的 linq 代码是:

var courses = (from c in db.Courses
           join cl in db.CourseLocations on c.CourseID equals cl.CourseID
           join cs in db.CourseSchedules on cl.CourseLocationID equals cs.CourseLocationID 

           where c.CourseStatusID == 1 && c.DeleteDate == null && ((c.CourseCategoryID == 1 && cs.EndDate >= courseEndDateFilter) || (c.CourseCategoryID == 3))

           select new
           {
               c.CourseID,
               CourseName = c.Name,
               CourseEndDate = cs.EndDate
           }).Distinct().OrderBy(o => o.CourseCategoryID).ThenBy(o => o.CourseName);

其中 courseEndDateFilter 是一个用于定义过滤日期的变量。

上述查询的问题是我得到了所有重复的课程,而不仅仅是具有 cs.EndDate MAX 值的课程

有没有办法(有效)做到这一点?

【问题讨论】:

  • 我认为你需要在这里做group by

标签: c# sql .net linq


【解决方案1】:

@Ehsan 是正确的。您需要一个分组依据,然后获取 EndDate 的最大值。给定以下模型:

    public class Course
    {
        public int CourseID { get; set; }
        public string Name { get; set; }
        public int CourseStatusID { get; set; }
        public int CourseCategoryID { get; set; }
        public DateTime? DeleteDate { get; set; }
    }

    public class CourseLocation
    {
        public int CourseLocationID { get; set; }
        public int CourseID { get; set; }
    }

    public class CourseSchedules
    {
        public int CourseLocationID { get; set; }
        public DateTime EndDate { get; set; }
    }

我在内存对象中创建了以下内容:

        var courses = new List<Course>
        {
            new Course { CourseID = 1, Name = "Test1", CourseCategoryID = 1, CourseStatusID = 1, DeleteDate = null },
            new Course { CourseID = 2, Name = "Test2", CourseCategoryID = 1, CourseStatusID = 1, DeleteDate = null },
            new Course { CourseID = 3, Name = "Test3", CourseCategoryID = 3, CourseStatusID = 1, DeleteDate = null }
        };
        var courseLocations = new List<CourseLocation>
        {
            new CourseLocation{ CourseID = 1, CourseLocationID = 1 },
            new CourseLocation{ CourseID = 2, CourseLocationID = 1 },
            new CourseLocation{ CourseID = 3, CourseLocationID = 1 },
            new CourseLocation{ CourseID = 1, CourseLocationID = 2 },
            new CourseLocation{ CourseID = 2, CourseLocationID = 2 },
            new CourseLocation{ CourseID = 3, CourseLocationID = 2 }

        };
        var courseSchedules = new List<CourseSchedules>
        {
            new CourseSchedules { CourseLocationID = 1, EndDate = DateTime.Now.AddDays(10) },
            new CourseSchedules { CourseLocationID = 1, EndDate = DateTime.Now.AddYears(1) }
        };

那么查询将如下获取 Max EndDate:

var result = (from c in courses
                join cl in courseLocations on c.CourseID equals cl.CourseID
                join cs in courseSchedules on cl.CourseLocationID equals cs.CourseLocationID

                where c.CourseStatusID == 1 && c.DeleteDate == null &&
                      (c.CourseCategoryID == 1 && cs.EndDate >= DateTime.Now || c.CourseCategoryID == 3)

                select new
                {
                    c.CourseID,
                    CourseName = c.Name,
                    CourseEndDate = cs.EndDate,
                    c.CourseCategoryID
                })
            .GroupBy(arg => new
            {
                arg.CourseID,
                arg.CourseName,
                arg.CourseCategoryID
            })
            .Select(grouping => new
            {
                grouping.Key.CourseID,
                grouping.Key.CourseName,
                CourseEndDate = grouping.Max(arg => arg.CourseEndDate),
                grouping.Key.CourseCategoryID
            })
            .OrderBy(o => o.CourseCategoryID)
            .ThenBy(o => o.CourseName); 

【讨论】:

    【解决方案2】:

    我不确定这是否可行,因为我实际上无法编译它。

    我马上看到的问题是,您在基地被一些东西过滤,其中一些不包括地点,但无论如何您想要地点的日期......

    var courses = (from c in db.Courses
    
           join cl in db.CourseLocations on c.CourseID equals cl.CourseID
           join cs in db.CourseSchedules on cl.CourseLocationID equals cs.CourseLocationID 
    
           where c.CourseStatusID == 1 && c.DeleteDate == null && (c.CourseCategoryID == 3 ||
           db.CourseLocations.Any(cl => cl.CourseID equals c.CourseID && 
               db.CourseSchedules.Any(cs => cs.CourseLocationID equals cl.CourseLocationID && 
                   ((c.CourseCategoryID == 1 && cs.EndDate >= courseEndDateFilter))
               )
           ))
    
           select new
           {
               c.CourseID,
               CourseName = c.Name,
               CourseEndDate = db.CourseSchedules.Where(cs => db.CourseLocations.Any(cl => cl.CourseID equals c.CourseID && cs.CourseLocationID equals cl.CourseLocationID)).Max(cs => cs.EndDate),
               c.CourseCategoryID
           });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多