2015-06-04 3 views
1

Запрос:получение записей из списка на основе категории

List<vwBookTitleKitsSummary> theseKits = (from k in _dataContext.vwBookTitleKitsSummaries 
                 where k.DateKitEnds > DateTime.Now && k.DateKitStarts <= DateTime.Now && k.IsDeleted == false 
                 orderby k.KitOrder, k.KitCode descending 
                 select k).ToList(); 

thesekits получил 6 результатов, как показано ниже (выделенные из них):

enter image description here

Я хочу, чтобы запрос, который возвращает один элемент из каждая категория например, я хочу, чтобы записи K1503, T1503 т.е.

Я хочу, чтобы первая запись, которые начинаются с K и первой записи, которые начинаются с T

Я пытался, как следующий:

List<vwBookTitleKitsSummary> theseKits = (from k in _dataContext.vwBookTitleKitsSummaries 
                 where k.DateKitEnds > DateTime.Now && k.DateKitStarts <= DateTime.Now && k.IsDeleted == false && (k.KitCode.StartsWith("K")) 
                 orderby k.KitOrder, k.KitCode descending 
                 select k).Take(1).ToList(); 

List<vwBookTitleKitsSummary> qry = (from k in _dataContext.vwBookTitleKitsSummaries 
          where k.DateKitEnds > DateTime.Now && k.DateKitStarts <= DateTime.Now && k.IsDeleted == false && (k.KitCode.StartsWith("T")) 
          orderby k.KitOrder, k.KitCode descending 
          select k).Take(1).ToList(); 
theseKits.AddRange(qry); 

Это будет возвращать записи с KitCode - K1503, T1503

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

+0

Попробуйте добавить условие ИЛИ в свой первый запрос. –

+0

добавление (k.KitCode.StartsWith («K») || k.KitCode.StartsWith («T») с результатами Take (2) с K1503, K1502. Мне нужен один от каждого KitCode. – user1282609

ответ

2

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

List<vwBookTitleKitsSummary> firstCategoryTheseKits = _dataContext 
    .vwBookTitleKitsSummaries.Where(k => k.DateKitEnds > DateTime.Now 
     && k.DateKitStarts <= DateTime.Now && k.IsDeleted == false).OrderBy(k => k.KitOrder) 
    .ThenByDescending(k => k.KitCode).GroupBy(k => k.KitCode[0]).Select(grps => grps.First) 
    .ToList(); 

Если вы хотите только для T или K, вы можете добавить где условие следующим образом:

List<vwBookTitleKitsSummary> firstCategoryTheseKits = _dataContext 
    .vwBookTitleKitsSummaries.Where(k => k.DateKitEnds > DateTime.Now 
    && k.DateKitStarts <= DateTime.Now && k.IsDeleted == false 
    && (k.KitCode[0] == 'T' || k.KitCode[0] == 'K')).OrderBy(k => k.KitOrder) 
    .ThenByDescending(k => k.KitCode).GroupBy(k => k.KitCode[0]) 
    .Select(grps => grps.First).ToList(); 

К сожалению мой запрос в краткой записи, вместо вашего обозначения запроса.

+0

Первый работает, спасибо, но если я хочу пропустить первый в каждой категории? Например, я хочу все, кроме T1503, K1503 в результатах выше 6. Пожалуйста, – user1282609

+1

, в этом случае вы можете добавить это check, который в основном выбирает только группы с более чем 1 записью и пропускает первую запись: GroupBy (k => k.KitCode [0]). Где (grps => grps.Count()> 1). Выберите (grps = > grps.Skip (1) .First()) –

+0

Он дает вторую запись из каждой категории. Например, я хочу исключить T1503, K1503, но я хочу T1502, T1501, K1502, K1501. grps.Skip (1). Первый() всегда возвращает один, мне нужно что-то вроде grps.Skip (1) .All(). Помогите. – user1282609

1

Вы можете сгруппировать по первому символу и взять первый элемент каждой группы:

from k in _dataContext.vwBookTitleKitsSummaries 
where k.DateKitEnds > DateTime.Now && k.DateKitStarts <= DateTime.Now 
    && k.IsDeleted == false 
orderby k.KitOrder, k.KitCode descending 
group k by k.KitCode.SubString(0,1) into grp 
select new { grp.Key, k = grp.FirstOrDefault() } 

Или просто select grp.FirstOrDefault() если вам нравится.

Смежные вопросы