Желаемый результат - это набор строк, содержащих сведения о враче и 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;
Я ценю ваши предложения.
Вашим лучшим выбором для такого рода вещей, чтобы начать профилирование запрос, который генерирует LINQ. Это, как говорится, первое, что я хотел бы рассмотреть, это пять свойств «NewCode». Если вы замените их на: 'NewCodes = nc.Codes.OrderByDescending (c => c.Volumn). Выберите (c => c.ProcedureCode) .Take (5)' что-то изменилось? –
@JasonBoyd, это было очень хорошо «первым делом» - сокращение времени запроса на 33% и строк SQL на 48%. Спасибо за подход – Scott
Я понимаю, почему я избегал этого раньше - не во всех строках будет 5 процедурных кодов, а сетка Telerik я привязываю это к (как model.ProcedureCode [x]) выдает исключение из пределов, когда он встречает кого-то с список менее 5 записей. Я постараюсь понять это, поэтому я могу продолжать в этом направлении. – Scott