#c# #entity-framework #linq #asp.net-core
#c# #entity-framework #linq #asp.net-core
Вопрос:
Я ломал голову над этим и не могу найти решение. У меня есть такой набор данных,
JobID DueDate VisitID
4024082 2020-07-31 5267157
4024082 2020-07-29 5263915
4024082 2020-08-04 5269154
4024082 2020-07-23 5258774
4024082 2020-07-22 5255307
Я хочу получить результирующий набор следующим образом,
JobID Duedate VisitID
4024082 2020-08-04 5269154
Я пробовал несколько способов, но не могу заставить его работать. мой запрос linq
var jobs = await (from j in _ctx.Jobs
join v in _ctx.Visits on j.JobID equals v.JobID
join p in _ctx.Products on j.ProductID equals p.ProductID
where j.IsProcessed== true
group v by new
{
v.JobID,
v.VisitID
}
into g
select new
{
JobId = g.Key,
DueDate = g.Max(x => x.DueDate),
VisitID = g.Key.VisitID
}).ToListAsync();
Любая помощь была бы высоко оценена. Спасибо
Комментарии:
1. Я этого не понимаю. Я имею в виду, я вижу только 1 таблицу, но я вижу соединение в вашем SQL-запросе??? значит, больше 1 таблицы?
2. Не включайте
DueDate
в группу by. Это странно, потому что вы хотите максимальную дату. Я действительно подозреваю, что вы хотите группировать только по идентификатору посещения.JobID
Не имеет значения, потому что у вас уже естьwhere
условие для этого идентификатора.3. @Iria отредактировал и добавил другое объединение. Я не поместил все соединения, чтобы избежать слишком большой путаницы.
4. @Silvermind удалил DueDate. Тем не менее, он возвращает 5 строк для меня вместо 1
5. Я не понимаю эту часть:
amp;amp; j.JobID == 4024082
в сочетании сToListAsync()
в конце. Это условие в сочетании с группой выглядит так, как вам нужноFirstOrDefaultAsync()
. Возможно, вы добавили этоJobID
для тестирования, но на самом деле этого нет в запросе, и вы на самом деле ищете максимальное значение duedate и сопутствующий идентификатор посещения для каждого идентификатора задания.
Ответ №1:
Вы не можете использовать Max
для получения более одного значения. Здесь вы должны использовать механизм сортировки.
Ниже приведен пример того, как сгруппировать задания по JobID
, а затем по каждой самой высокой дате с сопровождением VisitID
.
Вот пример. (Я использовал LINQPad для тестирования этого):
void Main()
{
var jobs = new[]
{
new Job { JobID = 4024082, DueDate = DateTime.ParseExact("2020-07-31", "yyyy-MM-dd", CultureInfo.InvariantCulture), VisitID = 5267157 },
new Job { JobID = 4024082, DueDate = DateTime.ParseExact("2020-07-29", "yyyy-MM-dd", CultureInfo.InvariantCulture), VisitID = 5263915 },
new Job { JobID = 4024082, DueDate = DateTime.ParseExact("2020-08-04", "yyyy-MM-dd", CultureInfo.InvariantCulture), VisitID = 5269154 },
new Job { JobID = 4024082, DueDate = DateTime.ParseExact("2020-07-23", "yyyy-MM-dd", CultureInfo.InvariantCulture), VisitID = 5258774 },
new Job { JobID = 4024082, DueDate = DateTime.ParseExact("2020-07-22", "yyyy-MM-dd", CultureInfo.InvariantCulture), VisitID = 5255307 },
};
var query = from job in jobs
group job by job.JobID into grp
select grp.OrderByDescending(g => g.DueDate).FirstOrDefault();
query.Dump();
}
public class Job
{
public int JobID { get; set; }
public DateTime DueDate { get; set; }
public int VisitID { get; set; }
}
Вывод:
JobID DueDate VisitID
4024082 4-8-2020 00:00:00 5269154
Комментарии:
1. Большое спасибо. Это сработало для меня 🙂 Мне пришлось сначала вставить значения из базы данных в объект класса заданий, а затем запросить объект класса заданий с помощью вашего запроса. Большое спасибо
Ответ №2:
Я думаю, проблема в том, что вы используете VisitId
как часть GroupBy
. Поскольку все VisitId
значения уникальны, вы получите одну запись на группу (и, следовательно, одну группу для каждой записи).
Возможно, вам следует присоединиться только JobId
, если вам нужна одна группа из этих образцов записей. Затем, чтобы получить VisitID
для строки, в которой была самая последняя DueDate
, мы можем упорядочить группу по DueDate
(по убыванию) и взять VisitID
из First()
записи:
var jobs = await (from j in _ctx.Jobs
join v in _ctx.Visits on j.JobID equals v.JobID
join p in _ctx.Products on j.ProductID equals p.ProductID
where j.IsProcessed== true
group v by v.JobID
into g
select new
{
JobId = g.Key,
DueDate = g.Max(x => x.DueDate),
VisitID = g.OrderByDecending(x => x.DueDate).First().VisitID
}).ToListAsync();
Комментарии:
1. Я получаю эту ошибку, когда использую OrderByDescending для DueDate . Не удалось перевести OrderByDescending(x => x.DueDate)’. Либо перепишите запрос в форме, которая может быть переведена, либо переключитесь на оценку клиента явно, вставив вызов AsEnumerable(), AsAsyncEnumerable(), ToList() или ToListAsync()
2. Можете ли вы попробовать изменить его на
VisitID = g.First(x => x.DueDate == g.Max(i => i.DueDate)).VisitID
и посмотреть, работает ли это? Извините, я не там, где я могу это проверить в данный момент.3. Теперь это выдает эту ошибку.Max(i => i.DueDate))’ не удалось перевести. Либо перепишите запрос в форме, которая может быть переведена,