ElenaRez Ответов: 1

Проблема поиска среднего значения для запроса nester linq


I'm implementing asp.net core project. And I have multiple tables called ApiApp, ApiAppHistory and Entity. In ApiApp table I have date field which is of type string (yyyy/mm/dd) and a field ApplicantID. In ApiAppHistory there is a field called LastReqStatus which is of type int and its related value is stored in Entity table. Now I want to group by Year, Month, LastReqStatus and ApplicantID to find for each month of a year for how many ApplicantID the LastReqStatus is equal to "Granted". And after finding that I want to know the average for each month of a year that all the ApplicantIDs' has lastReqStatus == "Granted". For the former I wrote a query like the following:

Но насчет среднего значения находки у меня нет никакого мнения, как я могу это сделать. Я буду признателен, если кто-нибудь мне поможет.
Например, у меня есть следующие данные в таблице ApiApp :
ApiApp data table:

ID:1 LastRequestStatus:1 ApplicantID:1 ApiRequestDate:2019/02/03
ID:2 LastRequestStatus:2 ApplicantID:1 ApiRequestDate:2019/02/16

ID:3 LastRequestStatus:10 ApplicantID:2 ApiRequestDate:2019/02/01
ID:4 LastRequestStatus:19 ApplicantID:2 ApiRequestDate:2019/02/20
ID:5 LastRequestStatus:31 ApplicantID:2 ApiRequestDate:2019/02/29


Таким образом, среднее значение должно быть:

(2 + 3)/2 это означает, что 2-это для ID:1 и ID:2, у которых есть один и тот же заявитель № 1, который запросил в феврале месяце, и 3-это для ID:3 и ID:4 и ID:5, у которых есть один и тот же заявитель № 2, который запросил в феврале месяце, и потому что в феврале месяце есть только два заявителя № 1 и № 2, таким образом, мы должны разделить числитель на 2.


И мои модели данных:

public partial class ApiApplicantHistory
    {
        public int Id { get; set; }
        public int? SentType { get; set; }
        public int? Reason { get; set; }
        public int? LastReqStatus { get; set; }
        public int? ApiAppId { get; set; }

        public virtual Apiapp ApiApp { get; set; }
        public virtual EntityType LastReqStatusNavigation { get; set; }
        public virtual EntityType SentTypeNavigation { get; set; }
        public virtual EntityType ReasonNavigation { get; set; }
    }

 public partial class EntityType
    {
        public EntityType()
        {
ApiApplicantHistoryLastReqStatusNavigation = new HashSet<ApiApplicantHistory>();            ApiApplicantHistorySentTypeNavigation = new HashSet<ApiApplicantHistory>();
            ApiApplicantHistoryReasonNavigation = new HashSet<ApiApplicantHistory>();
        }

        public int Id { get; set; }
        public string Name { get; set; }
        public string EntityKey { get; set; }

public virtual ICollection<ApiApplicantHistory> ApiApplicantHistoryLastReqStatusNavigation { get; set; }        public virtual ICollection<ApiApplicantHistory> ApiAppHistorySentTypeNavigation { get; set; }
        public virtual ICollection<ApiApplicantHistory> ApiAppHistoryReasonNavigation { get; set; }

    }
}

public partial class Apiapp
    {
        public Apiapp()
        {
            ApiApplicantHistory = new HashSet<ApiApplicantHistory>();
        }

        public int Id { get; set; }
public bool? IsDeleted { get; set; }

        public int? LastRequestStatus { get; set; }
        public int ApplicantID { get; set; }
        public string ApiRequestDate { get; set; }
        public virtual ICollection<ApiApplicantHistory> ApiApplicantHistory { get; set; }
    }


Что я уже пробовал:

var avg = from t1 in _context.Apiapp
          join t2 in _context.ApiAppHistory on t1.Id equals t2.ApiAppId
          join t3 in _context.Entity on t2.LastReqStatus equals t3.Id
          where t1.IsDeleted == false && t1.LastRequestStatus == t2.Id && t3.Name == "Granted"
                group new {t1,t2}
                by new { t2.LastReqStatus, Year = t1.ApiRequestDate.Substring(0, 4), Month = t1.ApiRequestDate.Substring(5, 2) , Applicant = t1.ApplicantId } into g

                    select new
                             {

                                 Year = g.Key.Year, 
                                 Month = g.Key.Month,
                                 GrantedCount = g.Count()
                             };

var GrantedReqAVG = avg.ToList();

1 Ответов

Рейтинг:
9

Maciej Los

Цитата:
В Благодаря таблице у меня есть поле Дата, которое имеет тип String

Это плохая идея, вы должны преобразовать его в datetime как можно скорее!

Единственный способ преобразовать строковые данные в правильное datetime-это (это также должно работать с EF):
1. DateTime.Parse()
или
2. DateTime.ParseExact()

Так...
//get proper values
var data = (from t1 in _context.Apiapp
            join t2 in _context.ApiAppHistory on t1.Id equals t2.ApiApplicantId
            join t3 in _context.Entity on t2.LastReqStatus equals t3.Id
            where t1.IsDeleted == false && t1.LastRequestStatus == t2.Id && t3.Name == "Granted" && t1.ApiRequestDate != null
            select new {ProperDate = DateTime.Parse(t1.ApiRequestDate), Applicant = t1.ApplicantId, ValueToGetAverage = ...})
            .ToList();

var avgdata = data
    .GroupBy(x=> new {FirstDayInMonth = x.ProperDate.AddDays(-x.ProperDate.Day+1), Applicant = Applicant})
    .Select(grp=> new
           {
               DateRange = g.Key.FirstDayInMonth,
               Applicatn = g.Key.Applicant,
               Average = grp.Average(x => x.ValueToGetAverage)
           }).ToList();