2013-03-28 4 views
1

Приносим извинения за звание, так как я не мог придумать краткую формулировку моей проблемы. Если у кого-то есть лучшее описание, отредактируйте его.Traverse dataset для проверки условий

цикла (таблица базы данных)

int PartNo (PK) 
int StepNo 
string Group 
Datetime Start 
Datetime Finish 
string Status 

Пример

PartNo | StepNo | Group | Start | Finish | Status 
    0  | 0  | Group1 | 1-1-01 | 1-2-01 | A 
    0  | 1  | Group2 | 1-2-01 | 1-3-01 | A 
    0  | 2  | Group3 | 1-3-01 | 1-4-01 | A 
    0  | 3  | Group1 | 1-4-01 | 1-5-01 | R 
    0  | 4  | Group1 | 1-5-01 | 1-6-01 |  
    0  | 5  | Group1 | 1-6-01 | 1-7-01 |  
    0  | 6  | Group1 | 1-7-01 |   |  
    0  | 7  | Group2 |   |   |  
...more PartNo... 

Позвольте мне начать давать краткое описание того, что мне нужно в "бизнес" слов. В этой таблице отображается элемент, одобренный несколькими группами. Как вы можете видеть в таблице примеров, group1, group2 и group 3 одобрили этот элемент, и он возвращается к группе 1. Пустые поля статуса представляют собой переназначения внутри этой группы, и вы можете увидеть, что он был переназначен несколько раз после отклонения на шаге 3. Вы также можете сказать, что текущий шаг равен 6, поскольку он имеет время start, но не finish времени. На PartNo может быть несколько отклонений.

Теперь вот описание моего сложного запроса. Мне нужно проверить, был ли недавний отказ. Это определяется отказом, происходящим в той же группе, что и текущая группа. Группы, участвующие между текущим шагом и шагом отбраковки, также должны быть одинаковыми, Group1 в этом случае, чтобы классифицироваться как недавнее отклонение. В этом примере текущий шаг равен 6, и мой запрос должен вернуть шаг 3, местоположение отклонения. Чтобы уточнить, были ли изменены шаги 4 или 5 в любой другой группе, запрос ничего не вернет. Я надеюсь, что в этом есть смысл.

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

Получить текущий шаг

Cycle.Where(c => c.Start.HasValue() && !c.Finish.HasValue()) 
    .GroupBy(c => c.PartNo) 
    .Select(g => new 
    { 
     PartNo = g.Key, 
     StepNo = g.Min(s => s.StepNo) 
    } 

Получить последний отвергает

Cycle.Where(c => c.Status == "R") 
    .GroupBy(c => c.PartNo) 
    .Select(g => new 
    { 
     PartNo = g.Key, 
     StepNo = g.Max(s => s.StepNo) 
    } 

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

EDIT:

Я думаю, можно было бы объединить два запроса выше в одну таблицу, содержащую PartNo, CurrentStep и RejectedStep. Отсюда я мог бы присоединиться к циклу, который дал бы мне все строки с текущего шага до отклоненного шага.

var combined = currentStep 
      .Join(rejectedStep, 
        c => c.PartNo, 
        r => r.PartNo, 
        (c,r) => new { PartNo = c.PartNo, Current = c.StepNo, Reject = r.Stepno}); 

Вставьте некоторые присоединиться запрос, чтобы получить StepNo <= Current && StepNo >= Reject

Я МОГ использовать foreach цикл, чтобы проверить, если группы в каждом из них есть то же самое, но я предпочел бы использовать LINQ, так что обработка происходит сторона базы данных. Как мне это достичь?

ответ

1

Я все еще не понимаю ваших требований. Вы указали в своем бизнес-описании, что хотите только вернуть строки, где Group - это то же самое, что и PartNo, но ни один из ваших образцов кода, похоже, не учитывает это.Этот запрос не очень, но это работает:

var results = 
    from c in Cycles 
    group c by new { c.PartNo, c.Group } into g 
    let c = g.Where(s => s.Start.HasValue && !s.Finish.HasValue) 
      .Select(s => s.StepNo) 
    let r = g.Where(s => s.Status == "R") 
      .Select(s => s.StepNo) 
    where r.Any() && c.Any() 
    select new 
    { 
     g.Key, 
     Steps = g.Where(s => s.StepNo <= c.Max() && s.StepNo >= r.Min()) 
    }; 

При запуске против вашего набора образцов, он возвращает: result set


Update

Вот еще один удар в этом. Этот запрос будет исключать случаи, когда group столбца изменяется в любой точке между отвергнутой стадией (r) и текущей стадией (c):

var results = 
    (from c in Cycles 
    group c by c.PartNo into g 
    let c = g.Where(s => s.Start.HasValue && !s.Finish.HasValue) 
      .Select(s => s.StepNo) 
    let r = g.Where(s => s.Status == "R") 
      .Select(s => s.StepNo) 
    where r.Any() && c.Any() 
    let steps = g.Where(s => s.StepNo <= c.Max() && s.StepNo >= r.Min()) 
    where steps.Select(x => x.Group).Distinct().Count() == 1 
    select new 
    { 
     g.Key, 
     Steps = steps 
    } 
+0

Я думаю, что этот вопрос очень близко к тому, что я требую. Позвольте мне попытаться пояснить. Я хочу знать, был ли элемент недавно отклонен. Существуют случаи, когда за шагом отката следуют переназначения внутри группы. Я узнаю, что элемент все еще «недавно отклонен», если все группы между текущим шагом и отклоненным шагом содержат одну и ту же группу. Если группа изменится в какой-то момент, это означает, что элемент был принят и переходит к следующему шагу. Если все группы совпадают между шагами отклоненного шага и текущего шага, я хочу вернуть отклоненный шаг. Надеюсь, что это поможет – Jeff

+0

Кроме того, я думаю, что ваше использование группировки 'c.Group' может работать некорректно, если на шаге 1 существует отклонение, т. Е. На ваш запрос будут возвращены два набора данных для одного PartNo, что нежелательно. – Jeff

+0

@Jeff См. Мой обновленный ответ. –

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