2015-07-26 6 views
1

Желаемый результат - это набор строк, содержащих сведения о враче и 5 лучших процедурах, которые они выполняли (по объему), которые не находятся в наших таблицах сравнения, - как минимум один раз в месяц. Даже с моим ограниченным опытом LINQ, мне удалось получить эту работу, но производительность в ужасном состоянии. В духе становления лучше в LINQ, я думал, что посмотрю, есть ли лучший способ приблизиться к этому (помимо кодирования в SQL).LINQ pivot top 5 строк в столбцах

Вот весь метод, хотя я считаю, что это окончательное утверждение (var report =), которое заслуживает наибольшего внимания.

//Get the Providers for the selected AccessLevel & Report Period 
var providerRiskLevels = GetProviderRiskLevelForAccessLevel(userAccessLevelId, reportPeriodId, providerNamePiece); 

short benchmarkYear = (
     from rp in db.ReportPeriods 
     where rp.ReportPeriodId == reportPeriodId 
     select rp.BenchmarkDataYear 
     ).FirstOrDefault(); 

byte Duration = (
     from rp in db.ReportPeriods 
     where rp.ReportPeriodId == reportPeriodId 
     select rp.Duration 
     ).FirstOrDefault(); 

//Summarize counts by procedure code (ignoring modifiers) 
var codeCounts = 
    from pp in db.ProviderProductions 
    //332 - restrict to valid codes 
    join pc in db.ProcedureCodes on pp.ProcedureCode equals pc.ProcedureCode1 
    where pp.ReportPeriodId == reportPeriodId 
     //show deleted codes as potential issue 
     && pc.TerminatedDate == null 
     && (codeFilter == null || pp.ProcedureCode == codeFilter) 
    join pc in db.PspsProcedures 
     on new { col1 = pp.ProcedureCode, col2 = benchmarkYear } equals new { col1 = pc.ProcedureCode, col2 = pc.Year } into left 
    from l_d in left.DefaultIfEmpty() 
    where l_d == null 
    group pp by 
     new { pp.ProviderId, pp.ProcedureCode } 
     into g 
     orderby g.Key.ProviderId, g.Sum(x => x.Volume) descending 
     where g.Sum(x => x.Volume) > Duration 
     select new NewCodesEntity 
     { 
      ProviderId = g.Key.ProviderId, 
      ProcedureCode = g.Key.ProcedureCode, 
      Volume = g.Sum(x => x.Volume) 
     }; 

//Get top 5 procedures performed by provider 
var newCodes = 
    from cc in codeCounts 
    group cc by 
     new { cc.ProviderId } 
     into g 
     select new ProviderNewCodesEntity 
     { 
      ProviderId = g.Key.ProviderId, 
      Codes = g.OrderByDescending(x => x.Volume).Take(5).ToList() 
     }; 

//Build the report 
var report = 
    from pr in providerRiskLevels 
    join nc in newCodes on pr.Provider.ProviderId equals nc.ProviderId 
    where pr.RiskCategoryId == RiskCategoryIds.VisibleRisk 
     && (filterRiskLevelNums.Contains(pr.RiskLevelNum)) 
     && (filterSpecialtyId == 0 || pr.Provider.Specialty.SpecialtyId == filterSpecialtyId) 
    select new ProbeAuditEntity 
    { 
     ProviderId = pr.Provider.ProviderId, 
     ProviderName = pr.Provider.Name, 
     ProviderCode = pr.Provider.ProviderCode, 
     SpecialtyName = pr.Provider.Specialty.Name, 
     SpecialtyCode = pr.Provider.Specialty.SpecialtyCode, 
     VisibleRisk = pr.RiskScore, 
     NewCode1 = nc.Codes.OrderByDescending(c => c.Volume).FirstOrDefault().ProcedureCode, 
     NewCode2 = nc.Codes.OrderByDescending(c => c.Volume).Skip(1).FirstOrDefault().ProcedureCode, 
     NewCode3 = nc.Codes.OrderByDescending(c => c.Volume).Skip(2).FirstOrDefault().ProcedureCode, 
     NewCode4 = nc.Codes.OrderByDescending(c => c.Volume).Skip(3).FirstOrDefault().ProcedureCode, 
     NewCode5 = nc.Codes.OrderByDescending(c => c.Volume).Skip(4).FirstOrDefault().ProcedureCode 
    }; 
return report; 

Я ценю ваши предложения.

+0

Вашим лучшим выбором для такого рода вещей, чтобы начать профилирование запрос, который генерирует LINQ. Это, как говорится, первое, что я хотел бы рассмотреть, это пять свойств «NewCode». Если вы замените их на: 'NewCodes = nc.Codes.OrderByDescending (c => c.Volumn). Выберите (c => c.ProcedureCode) .Take (5)' что-то изменилось? –

+0

@JasonBoyd, это было очень хорошо «первым делом» - сокращение времени запроса на 33% и строк SQL на 48%. Спасибо за подход – Scott

+0

Я понимаю, почему я избегал этого раньше - не во всех строках будет 5 процедурных кодов, а сетка Telerik я привязываю это к (как model.ProcedureCode [x]) выдает исключение из пределов, когда он встречает кого-то с список менее 5 записей. Я постараюсь понять это, поэтому я могу продолжать в этом направлении. – Scott

ответ

0

Дайте этому попытку для отчета:

//Build the report 
var report = 
    (from pr in providerRiskLevels 
    join nc in newCodes on pr.Provider.ProviderId equals nc.ProviderId 
    where pr.RiskCategoryId == RiskCategoryIds.VisibleRisk 
     && filterRiskLevelNums.Contains(pr.RiskLevelNum) 
     && (filterSpecialtyId == 0 
      || pr.Provider.Specialty.SpecialtyId == filterSpecialtyId) 
    select new 
    { 
     RiskLevel = pr, 
     NewCodes = nc.Codes.OrderByDescending(c => c.Volumn).Select(c => c.ProcedureCode).Take(5) 
    }) 
    .AsEnumerable() 
    .Select(x => new ProbeAuditEntity 
    { 
     ProviderId = x.RiskLevel.Provider.ProviderId, 
     ProviderName = x.RiskLevel.Provider.Name, 
     ProviderCode = x.RiskLevel.Provider.ProviderCode, 
     SpecialtyName = x.RiskLevel.Provider.Specialty.Name, 
     SpecialtyCode = x.RiskLevel.Provider.Specialty.SpecialtyCode, 
     VisibleRisk = x.RiskLevel.RiskScore, 
     NewCodes = x.NewCodes.Concat(Enumerable.Repeat(<DefaultProcedureCodeHere>, 5)).Take(5) 
    }); 

Или, если ProbeAuditEntity класса вы можете сделать это:

//Build the report 
var report = 
    (from pr in providerRiskLevels 
    join nc in newCodes on pr.Provider.ProviderId equals nc.ProviderId 
    where pr.RiskCategoryId == RiskCategoryIds.VisibleRisk 
     && filterRiskLevelNums.Contains(pr.RiskLevelNum) 
     && (filterSpecialtyId == 0 
      || pr.Provider.Specialty.SpecialtyId == filterSpecialtyId) 
    select new ProbeAuditEntity 
    { 
     ProviderId = x.RiskLevel.Provider.ProviderId, 
     ProviderName = x.RiskLevel.Provider.Name, 
     ProviderCode = x.RiskLevel.Provider.ProviderCode, 
     SpecialtyName = x.RiskLevel.Provider.Specialty.Name, 
     SpecialtyCode = x.RiskLevel.Provider.Specialty.SpecialtyCode, 
     VisibleRisk = x.RiskLevel.RiskScore, 
     NewCodes = nc.Codes.OrderByDescending(c => c.Volumn).Select(c => c.ProcedureCode).Take(5) 
    }) 
    .ToList(); 

report 
.ForEach(x => x.NewCodes = x.NewCodes.Concat(Enumerable.Repeat(<DefaultProcedureCodeHere>, 5)).Take(5); 
+0

Спасибо. Я пошел с первым вариантом, а также объединил два, теперь очень похожих, заявления «newCodes =» и «report =», – Scott