2013-04-26 5 views
1

У меня есть данные, которые выглядят как:
Данные упорядочиваются по идентификатору processID, а затем по дате начала.
Дата начала шага определяет последовательность шагов. Каждый шаг утвержден утверждающий (утверждающего идентификаторы ниже произвольны)SQL Server - Возвращает наборы с повторяющимися значениями в последовательных записях

╔═══════════╦══════════════════════════╦═══════════════╦════════════╗ 
║ ProcessID ║   StepName   ║Step Start Date║ ApproverID ║ 
╠═══════════╬══════════════════════════╬═══════════════╬════════════╣ 
║   1 ║ Supervisor Approval  ║1/1/2013 07:24 ║ A   ║ 
║   1 ║ Sales Manager Approval ║1/1/2013 13:35 ║ B   ║ 
║   1 ║ General Manager Approval ║1/3/2013 08:00 ║ B   ║ 
║   1 ║ CEO Approval    ║1/5/2013 14:40 ║ C   ║ 
║   2 ║ Supervisor Approval  ║1/2/2013 07:00 ║ A   ║ 
║   2 ║ Sales Manager Approval ║1/2/2013 08:00 ║ B   ║ 
║   2 ║ General Manager Approval ║1/2/2013 09:00 ║ C   ║ 
║   2 ║ CEO Approval    ║1/2/2013 10:00 ║ B   ║ 
╚═══════════╩══════════════════════════╩═══════════════╩════════════╝ 

мне нужен TSQL запрос, который будет возвращен [ProcessID] 's для любого процесса, который имеет один и тот же ApproverID в 2 или более последовательных шаги.

Таким образом, в приведенном выше примере ProcessID # 1 будет возвращен, так как Approver B одобрил шаги 2 и 3 (последовательно). ProcessID # 2 не будет возвращен, потому что, несмотря на то, что Утвердитель B одобрил шаги 2 и 4, они не были последовательными.

Вот SQL скрипку с настройкой схемы и некоторые выборки данных: SQL Fiddle

Любая помощь будет принята с благодарностью!

+2

Как мы должны знать последовательность для шагов ?? – Lamak

+0

Вы пробовали написать запрос? –

+0

Последовательность шагов уже установлена ​​в приведенном выше наборе результатов. Они были заказаны к дате начала шага. К сожалению, нет числового идентификатора или чего-либо подобного, который сопоставляет имя шага идентификатору последовательности. Может быть включен столбец datetime, который является датой начала шага (каким образом данные в настоящее время упорядочены). –

ответ

1

Это возвращает процесс 1, как это требуется от набора данных:

with nextSteps as 
(
    select s.ProcessID 
    , disapprove = case when s.ApproverID <= n.ApproverID or n.ApproverID is null 
     then 0 else 1 end 
    from steps s 
    outer apply 
    (
     select top 1 ApproverID 
     from steps n 
     where s.ProcessID = n.ProcessID 
     and s.StepStartDate < n.StepStartDate 
     order by n.StepStartDate 
    ) n 
) 
select ProcessID 
from nextSteps 
group by ProcessID 
having sum(disapprove) = 0 

SQL Fiddle with demo.

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

Если одна или несколько строк не работают, не возвращайте ProcessID.

Редактировать после комментария:

with nextSteps as 
(
    select s.ProcessID 
    , disapprove = case when s.ApproverID = n.ApproverID then 1 else 0 end 
    from steps s 
    outer apply 
    (
     select top 1 ApproverID 
     from steps n 
     where s.ProcessID = n.ProcessID 
     and s.StepStartDate < n.StepStartDate 
     order by n.StepStartDate 
    ) n 
) 
select ProcessID 
from nextSteps 
group by ProcessID 
having sum(disapprove) > 0 

SQL Fiddle with demo.

Этот новый немного изменил запрос работает для следующих моделей утверждающих, как показан в SQL Fiddle:

ProcessID 1: A, B, B, C - Имеет последовательные утверждающие, должен быть возвращен.

ProcessID 2: A, B, C, B - Не имеет последовательных утверждений, не должен быть возвращен.

ProcessID 3: A, B, C, D - Не имеет последовательных утверждений, не должен быть возвращен.

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

Я также проверил с данными в SQL Fiddle добавленных - кажется, работает:

SQL Fiddle with more data.

+0

Я ценю ответ, но в этом есть две вещи. Во-первых, идентификаторы утвердителя произвольны, они не всегда будут A, B, C и т. Д. По порядку. Во-вторых, если бы я изменил утвердителей processID # 2 на A, B, C, D, тогда ваш запрос также вернет его, чего не должно быть, поскольку не было двух последовательных шагов, одобренных одним и тем же лицом. –

+1

@ M.Ob, я немного изменил запрос и, похоже, работает по мере необходимости. Дополнительная информация была очень полезной, помогая уточнить требования. –

+0

Ian, спасибо. Я закончил тем, что решил использовать ваш запрос в качестве отправной точки. Я введу свое решение в качестве ответа, но буду отмечать ваш ответ, потому что я бы не понял его без вашей помощи. Благодаря! –

0

Вот что я закончил с, благодаря помощи Яна:

WITH Steps AS 
(
    SELECT 
    [CurStep].[ProcessID], 
    ConsecutiveApproval = 
     CASE 
     WHEN [CurStep].[ApproverID] = [NextStep].[ApproverID] THEN 1 
     ELSE 0 
     END 
    FROM [Processes] AS CurStep 
    OUTER APPLY 
    (
     SELECT TOP 1 
     [NextStep].[ApproverID] 
     FROM 
     [Processes] AS NextStep 
     WHERE 
     [CurStep].[ProcessID] = [NextStep].[ProcessID] 
     AND [CurStep].[StepStartDate] < [NextStep].[StepStartDate] 
     ORDER BY [NextStep].[StepStartDate] 
    ) AS NextStep 
) 
SELECT [ProcessID] 
FROM  [Steps] 
GROUP BY [Steps].[ProcessID] 
HAVING SUM([ConsecutiveApproval]) > 0 

Working SQL Fiddle

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