2015-12-29 3 views
3

У меня есть таблица с 3 значениями.Строки возврата SQL Server, где поле изменилось

ID  AuditDateTime  UpdateType 
12  12-15-2015 18:09 1 
45  12-04-2015 17:41 0 
75  12-21-2015 04:26 0 
12  12-17-2015 07:43 0 
35  12-01-2015 05:36 1 
45  12-15-2015 04:35 0 

Я пытаюсь вернуть только те записи, где UpdateType изменился с AuditDateTime на основе идентификаторов. Таким образом, в этом примере ID 12 изменяется от записи 12-15 к записи 12-17. Я бы хотел, чтобы эта запись вернулась. Будет несколько экземпляров ID 12, и мне нужны все записи, возвращаемые, когда ID изменился с предыдущей записи. Я попытался добавить row_number, но он не вставлялся последовательно, потому что записи не находятся в таблице по порядку. Я потратил немало времени на поиски без везения. Любая помощь будет принята с благодарностью.

ответ

3

С помощью КТР это можно найти предыдущую запись, основанную на порядке AuditDateTime

WITH CTEData AS 
(SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY AuditDateTime) [ROWNUM], * 
FROM @tmpTable) 
SELECT A.ID, A.AuditDateTime, A.UpdateType 
FROM CTEData A INNER JOIN CTEData B 
     ON (A.ROWNUM - 1) = B.ROWNUM AND 
      A.ID = B.ID 
WHERE A.UpdateType <> B.UpdateType 

Внутренний Присоединиться к CTE даст в одном запросе как текущую запись (Алиас таблицы), так и предыдущую строку (Алиас таблицы).

+0

Это все равно вернет ID 12, когда есть строка с датой 12-16-2015 и обновит тип 0 для ID 12. –

+0

Он должен вернуть идентификатор 12, так как запись 12-15-2015 имеет тип обновления 1. Возвращенные данные будут для этой новой записи. – Steven

+0

Попробуйте вставить строку с датой: 12-16-2015, тип обновления: 0 и ID 12 .. В этом случае он все равно вернет ID 12, на который не просят сделать это. (_ Мне нужны все записи, возвращаемые в том случае, когда обновленный тип идентификатора изменился с его предыдущей записи_) –

0

Это должно делать то, что вы пытаетесь сделать, я считаю,

SELECT 
    T1.ID, 
    T1.AuditDateTime, 
    T1.UpdateType 
FROM 
    dbo.My_Table T1 
INNER JOIN dbo.My_Table T2 ON 
    T2.ID = T1.ID AND 
    T2.UpdateType <> T1.UpdateType AND 
    T2.AuditDateTime < T1.AuditDateTime 
LEFT OUTER JOIN dbo.My_Table T3 ON 
    T3.ID = T1.ID AND 
    T3.AuditDateTime < T1.AuditDateTime AND 
    T3.AuditDateTime > T2.AuditDateTime 
WHERE 
    T3.ID IS NULL 

В качестве альтернативы:

SELECT 
    T1.ID, 
    T1.AuditDateTime, 
    T1.UpdateType 
FROM 
    dbo.My_Table T1 
INNER JOIN dbo.My_Table T2 ON 
    T2.ID = T1.ID AND 
    T2.UpdateType <> T1.UpdateType AND 
    T2.AuditDateTime < T1.AuditDateTime 
WHERE 
    NOT EXISTS 
    (
     SELECT * 
     FROM 
      dbo.My_Table T3 
     WHERE 
      T3.ID = T1.ID AND 
      T3.AuditDateTime < T1.AuditDateTime AND 
      T3.AuditDateTime > T2.AuditDateTime 
    ) 

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

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

0

Вы можете использовать функцию окна lag(), чтобы найти предыдущее значение для того же ID. Теперь вы можете выбрать только те строки, которые вносят изменения:

select * 
from (
     select lag(UpdateType) over (
        partition by ID 
        order by AuditDateTime) as prev_updatetype 
     ,  * 
     from YourTable 
     ) sub 
where prev_updatetype <> updatetype 

Example at SQL Fiddle.

+0

@Andomar Мы не знаем, какая версия SQL Server использовалась. Укажите, что функция LAG доступна в SQL Server 2012 и более поздних версиях. –

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