2016-01-12 6 views
2

У меня есть следующая таблица:Удаление строки из запроса

OrderID | OldOrderID | Action | EntryDate | Source 
    1 |  NULL  | Insert | 2016-01-12| A 
    1 |  NULL  | Remove | 2016-01-13| A 
    2 |  NULL  | Insert | 2016-01-12| B 
    3 |  NULL  | Insert | 2016-01-12| C 
    4 |  3  | Insert | 2016-01-13| C 
    4 |  NULL  | Remove | 2016-01-14| C 

Я хочу, чтобы запросить все заказы, которые в настоящее время активные заказы - они не имеют действия удалить. В настоящее время я делаю это с этим запросом:

WITH Active AS 
(
    SELECT *, rn = ROW_NUMBER() 
    OVER (PARTITION BY OrderID,Source ORDER BY EntryDate DESC) 
    FROM Orders 
) 
SELECT * 
FROM Active WHERE [Action] <> 'Remove' AND rn = 1; 

Проблема заключается в том, что некоторые заказы получить дочерние заказы (OrderID 3 получает ребенок OrderId 4), а если ребенок когда-либо получает Действие Удалить запрос также должен игнорировать родителя, но с текущим запросом он доцент.

Короче текущего запроса получает меня этот результат:

OrderID | OldOrderID | Action | EntryDate | Source 
    2 |  NULL  | Insert | 2016-01-12| B 
    3 |  NULL  | Insert | 2016-01-12| C 

Но мне нужен этот результат:

OrderID | OldOrderID | Action | EntryDate | Source 
    2 |  NULL  | Insert | 2016-01-12| B 

Можно ли исправить запрос, чтобы получить результат, как это?

+1

Может ли ребенок заказать собственный ребенок? –

+0

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

+0

Также некоторые строки имеют значение OldOrderID равное 0 или OrderID instrad, равное нулю, когда у них нет детей – Hauba

ответ

0

Я также задал вопрос о dba stackexchange и получил следующее answer, которое хорошо работает.

0

Попробуйте это:

;WITH CTE AS (
    SELECT OrderID, OldOrderID, Action, EntryDate, Source, 
      COUNT(CASE WHEN Action = 'Remove' THEN 1 END) 
      OVER (PARTITION BY OrderID) AS IsRemoved, 
      ROW_NUMBER() OVER (PARTITION BY OrderID ORDER BY EntryDate) AS rn 
    FROM Orders 
) 
SELECT c1.* 
FROM CTE AS c1 
LEFT JOIN CTE AS c2 ON c1.OrderID = c2.OldOrderID AND c2.IsRemoved >= 1 
WHERE c1.rn = 1 AND c1.IsRemoved = 0 AND c2.IsRemoved IS NULL 

приведенный выше запрос использует COUNT() OVER() для того, чтобы подсчитать количество вхождений Action = 'Remove' в пределах каждого раздела OrderID. Следовательно, значение IsRemoved, равное или превышающее 1, идентифицирует «удаленный» порядок.

+0

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

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