Выберите один из результатов сопоставления из последней записи группы с даты - PullRequest
0 голосов
/ 02 ноября 2018

У меня есть несколько клиентов, которые входят в группу, обозначенную идентификатором группы.

Я хотел бы получить 1 запись из связанной таблицы для каждого из подходящих членов группы (последняя запись до определенной даты).

В настоящее время я запрашиваю список членов группы, затем для каждого участника я запускаю другой запрос, чтобы получить последнюю запись за определенную дату.

Я хотел бы сделать это с одним запросом, так как я могу получить связанные записи таблицы, используя идентификатор группы - однако это возвращает все записи, связанные с группой (плохо).

Если я использую first или default, я получаю результаты только для первой найденной группы. Я хочу 1 запись от каждого члена группы.

Мой код (возвращает все связанные записи членов группы):

  List<Record> rs = (from x in db.Records where (x.Customer.Group == udcg && x.CloseDate < date && x.CloseDate < earlyDate) orderby x.CloseDate descending select x).ToList();

Но я просто хочу по одному от каждого вместо все .

Код, который я сейчас использую:

var custs = (from x in db.Customers where (x.group == udcg) select new { x.CustomerID }).ToList();
    expected = custs.Count();
    foreach (var cust in custs)
    {
      Record br = (from x in db.Records where (x.Customer.CustomerID == cust.CustomerID && x.CloseDate < date && x.CloseDate < earlyDate)) orderby x.CloseDate descending select x).FirstOrDefault();
      if (br != null)
        {
           total = (double)br.BillTotal;
           cnt++;        
        }
    }

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Пожалуйста, попробуйте это, оцените список записей.

DateTime certain_date = new DateTime(2018, 11, 1);

List<Record> records = new List<Record>();

var query = records.GroupBy(x => x.Customer.Group).Select(g => new { Group = g.Key, LastRecordBeforeCertainDate = g.Where(l => l.CloseDate < certain_date).OrderByDescending(l => l.CloseDate).FirstOrDefault() });
0 голосов
/ 02 ноября 2018

Я думаю, что это может сработать

db.Customers
    .Where(c => c.group == udcg)
    .Select(c => db.Records
            .Where(r => r.Customer.CustomerID == c.CustomerID)
            .Where(r => r.CloseDate < date)
            .Where(r => r.CloseDate > date.AddMonths(-2))
            .OrderByDescending(r => r.CloseDate)
            .FirstOrDefault())
    .Where(r => r != null)

Переводится в один SQL-запрос. Это означает, что он использует одну поездку на сервер. Это может быть довольно большой разницей в производительности по сравнению с циклом foreach. Если вы посмотрите на сгенерированный sql, это будет что-то вроде

SELECT some columns
FROM Customers
OUTER APPLY (
    SELECT TOP (1) some columns
    FROM Records
    WHERE some conditions
    ORDER BY CloseData DESC
    )

С точки зрения производительности самого запроса, я не ожидал бы проблем здесь, у сервера sql не должно быть проблем с оптимизацией этой формы (по сравнению с другими способами, которыми вы могли бы написать этот запрос).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...