【问题标题】:C# Linq to SQL, find Min and Max dates in grouped rowsC# Linq to SQL,在分组行中查找最小和最大日期
【发布时间】:2017-09-04 05:56:43
【问题描述】:

我有一个大型学区数据库,我需要从中确定学期、学期和全年的开始和结束日期。每所学校可能有不同的假期(与周末一起计算到学期开始日期),尽管这不太可能。 我已经了解了学校、他们的假期和每个学期的结束日期,并由此计算出每个学期的开始日期。到目前为止,一切都很好。但是有些学校有一些按学期注册的班级和其他全年(9月至6月)的班级。所以我希望我的最终返回日期看起来像(这代表许多学校之一):

SchoolId SchoolYear TermCode    TermBegin        TermEnd      TermCodeId
8CFD1     2016      TM1         08/29/2016       10/07/2016     F375E7
8CFD1     2016      TM2         10/10/2016       11/25/2016     898EF5
8CFD1     2016      TM3         11/28/2016       02/01/2017     F5140C
8CFD1     2016      TM4         02/02/2017       03/10/2017     DD95B1
8CFD1     2016      TM5         03/13/2017       05/05/2017     BE3635
8CFD1     2016      TM6         05/08/2017       06/09/2017     2B94F0
8CFD1     2016      YR          08/29/2016       06/09/2017     D97C9C

我得到的最接近的是这个查询(使用我计算开始日期的结果):

from tdf in ReturnFromCalculatingStartDate 
            join tcd in SCH_YR_TRM_CODES on tdf.SchoolYearTermDefGu equals tcd.SCHOOL_YEAR_TRM_DEF_GU
            orderby tcd.TERM_CODE
            select new TermResult {     
                SchoolId = testOrgGu,
                SchoolYear = testSchoolyear,
                TermCode = tcd.TERM_CODE,
                TermBegin = tdf.TermStartDate,
                TermEnd = tdf.TermEndtDate,
                TermCodeId = tcd.SCHOOL_YEAR_TRM_CODES_GU

这会正确返回术语,但我会为每个术语获得一年 (YR)。我需要的是一个 YR 行,其中包含 YR 行的 Min(TermBegin) 和 Max(TermEnd)。我需要对 SchoolId 和 TermCode 进行分组并获取每个唯一代码的最小值和最大值,但我不知道如何。

我从上面的 Linq 得到的数据如下。 Min(TermBegin) YR 行中的 TermCodeId 是我需要在结果中包含的 TermCodeId。

SchoolId    SchoolYear  TermCode  TermBegin    TermEnd     TermCodeId
   8CFD1    2016         TM1        08/29/2016  10/07/2016  F375E7
   8CFD1    2016         TM2        10/10/2016  11/25/2016  898EF5
   8CFD1    2016         TM3        11/28/2016  02/01/2017  F5140C
   8CFD1    2016         TM4        02/02/2017  03/10/2017  DD95B1
   8CFD1    2016         TM5        03/13/2017  05/05/2017  BE3635
   8CFD1    2016         TM6        05/08/2017  06/09/2017  2B94F0
   8CFD1    2016         YR         08/29/2016  10/07/2016  d97C9C
   8CFD1    2016         YR         10/10/2016  11/25/2016  e30980
   8CFD1    2016         YR         11/28/2016  02/01/2017  ef5de2
   8CFD1    2016         YR         02/02/2017  03/10/2017  bbe78f
   8CFD1    2016         YR         03/13/2017  05/05/2017  ca28a7
   8CFD1    2016         YR         05/08/2017  06/09/2017  2340c1

感谢您的帮助,走到这一步很有挑战性。

【问题讨论】:

  • SchoolId, SchoolYear and TermCode 对它们进行分组。如果YRTermCode可能是Year或者其他值,那么先在数据库端修复数据。找出所有用于年份的不同代码,并将它们都设为一个值:它是一个代码,所以它应该是相同的。
  • 很遗憾,我无法控制数据。但是 TermCode 对于年级和学校是一致的,所以我删除了那个位。我知道我需要分组,然后取最小值和最大值,但我不知道该怎么做。

标签: c# linq group-by min


【解决方案1】:

以下是解决此问题的方法:

  1. 获取所有TermCode 不是YR 的记录
  2. 获取TermCodeYR 的所有记录,但将它们按SchoolIdSchoolYearTermCodeTermCodeId 分组,并为每个组获取Max(TermBegin)Max(TermEnd)
  3. 对上述第 1 步和第 2 步中的结果执行Union

第 1 步

我们只需要像这样在您的查询中添加where 子句:

where tcd.TERM_CODE != "YR"

但是让我们将查询保存在一个变量中,这样它就更具可读性。请注意添加where 子句:

var excludingYr =
    from tdf in ReturnFromCalculatingStartDate
    join tcd in SCH_YR_TRM_CODES on tdf.SchoolYearTermDefGu
        equals tcd.SCHOOL_YEAR_TRM_DEF_GU
    where tcd.TERM_CODE != "YR"
    orderby tcd.TERM_CODE
    select new TermResult
    {
        SchoolId = testOrgGu,
        SchoolYear = testSchoolyear,
        TermCode = tcd.TERM_CODE,
        TermBegin = tdf.TermStartDate,
        TermEnd = tdf.TermEndtDate,
        TermCodeId = tcd.SCHOOL_YEAR_TRM_CODES_GU
    };

第 2 步

我们需要添加一个where 子句和一个group byMin 和'Max':

var yearRecords =
    from tdf in ReturnFromCalculatingStartDate
    join tcd in SCH_YR_TRM_CODES on tdf.SchoolYearTermDefGu
        equals tcd.SCHOOL_YEAR_TRM_DEF_GU
    where tcd.TERM_CODE == "YR"
    orderby tcd.TERM_CODE
    group tdf by new
        {
            SchoolId = testOrgGu,
            SchoolYear = testSchoolyear,
            TermCode = tcd.TERM_CODE,
            TermCodeId = tcd.SCHOOL_YEAR_TRM_CODES_GU
    } into yrs
    select new TermResult
    {
        SchoolId = yrs.Key.SchoolId,
        SchoolYear = yrs.Key.testSchoolyear,
        TermCode = yrs.Key.TermCode,
        TermBegin = yrs.Min(x => x.TermBegin),
        TermEnd = yrs.Max(x => x.TermBegin),
        TermCodeId = yrs.Key.TermCodeId
    };

第 3 步

让我们执行一个Union

var finalQuery = excludingYr.Union(yearRecords);

因为你需要TermCodeId,所以第二步会有重复的记录,所以我们需要在这里做一些体操来去除重复。请参阅this 答案以了解如何完成该部分。

请注意,我无法编译或测试上述内容,因此您可能需要对其进行调整,但步骤都在那里,并且由于您拥有数据,因此应该不容易做到。

【讨论】:

  • 谢谢 CodingYoshi,我一直在努力解决这个问题。明天当我可以访问我的所有数据时,我会尝试它,并告诉你它是如何工作的。
猜你喜欢
  • 1970-01-01
  • 2011-01-09
  • 2015-03-12
  • 1970-01-01
  • 2012-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多