SQL запрос - как получить, когда строка впервые получила определенное значение - PullRequest
2 голосов
/ 16 сентября 2010

У меня есть таблица с такими строками:

   ID  StatusId   Date
    1    1        2001-01-01
    2    1        2001-01-02
    3    2        2001-01-03
    4    3        2001-01-04
    5    1        2001-01-05
    6    2        2001-01-06
    7    2        2001-01-07
    8    1        2001-01-08
    9    1        2001-01-09

Мне нужно получить дату, когда текущее значение статуса было первоначально изменено.В приведенном выше примере последнее значение равно 1, и оно изменяется в строке 8, поэтому результатом будет 2001-01-08.

Как бы вы это сделали?

Если вам нужнотаблица для тестирования, вот она:

DECLARE @Tbl AS TABLE (ID INT, StatusId INT, Date DATETIME)

INSERT INTO @Tbl(ID, StatusId, Date)
SELECT 1,1,'2001-01-01' UNION
SELECT 2,1,'2001-01-02' UNION
SELECT 3,2,'2001-01-03' UNION
SELECT 4,3,'2001-01-04' UNION
SELECT 5,1,'2001-01-05' UNION
SELECT 6,2,'2001-01-06' UNION
SELECT 7,2,'2001-01-07' UNION
SELECT 8,1,'2001-01-08' UNION
SELECT 9,1,'2001-01-09' 

    SELECT * FROM @Tbl

Ответы [ 5 ]

2 голосов
/ 16 сентября 2010

Этот должен получить то, что вы ищете:

declare @LastStatusID int
declare @LastDate datetime
declare @LastID int

declare @LastChangeID int

/* get last record */
select top 1 @LastStatusID = StatusID, @LastDate = Date, LastID = ID
from @Tbl
order by ID desc

/* get last record with a different status */
select top 1 @LastChangeID = ID
from @Tbl
where ID < @LastID and StatusID <> @LastStatusID
order by ID desc

/* get the first next record - this would get you the last record as well whe it's just been set */
select top 1 Date
from @Tbl
where ID > @LastChangeID
order by ID asc

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

как один запрос

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

select top 1 Date
from @tbl t1
    left join @tbl t2
    on (t2.ID = t1.ID - 1)
where (isnull(t2.StatusID, -1) <> t1.StatusID)
order by ID desc

Последнее предложение where изменяет значение null (при отсутствии верхней записи) на -1. Если у вас есть статус с этим значением, вы должны изменить это число на какое-то несуществующее значение статуса.

2 голосов
/ 16 сентября 2010

Примерно так:

DECLARE @CurrentID INT, @CurrentDate Date

SELECT TOP 1 @CurrentID = ID, @CurrentDate = Date FROM TABLE
ORDER BY Date DESC

SELECT TOP 1 ID, StatusID, Date
FROM Table
WHERE Date < @CurrentDate
AND ID <> @CurrentID
ORDER BY Date DESC
0 голосов
/ 16 сентября 2010

Вот что я наконец-то придумал:

SELECT T1.ID, T1.StatusId, MIN(T3.Date)
FROM @Tbl T1 INNER JOIN @Tbl T3 ON T1.StatusId = T3.StatusId
WHERE T3.Date > (SELECT MAX(Date) FROM @Tbl T2 WHERE T2.StatusId <> T1.StatusId)
AND T1.ID = (SELECT MAX(ID) FROM @Tbl)
GROUP BY T1.ID, T1.StatusId

и он делает то, что мне было нужно ... спасибо всем

0 голосов
/ 16 сентября 2010

Если в таблице гарантированно есть одна запись в день (согласно вашим образцам данных), то может работать следующее:

select MAX(t1.Date)
from
   @Tbl t1
      inner join
   @Tbl t2
      on
          t1.Date = DATEADD(day,1,t2.Date) and
          t1.StatusId <> t2.StatusID

Конечно, можно уточнить это, если есть другие столбцы/ критерии, если значение, возможно, никогда не изменилось вообще.Трудно сказать на примере небольшого размера выборки / вывода.

Редактировать 1 Если мое предположение о вводе одной записи в день неверно, предложение from может быть:

from
   @Tbl t1
      inner join
   @Tbl t2
      on
          t1.Date > t2.Date and
          t1.StatusId <> t2.StatusID
      left join
   @Tbl t_successive
      on
          t1.Date > t_successive.Date and
          t2.Date < t_successive.Date
where
   t_successive.ID is null

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

0 голосов
/ 16 сентября 2010

попробуй

select Date
from @Tbl
where StatusId = (
    select StatusId
    from @Tbl
    order by ID desc limit 1)
order by ID desc
limit 1,1

Пожалуйста, проверьте, поддерживает ли ваша база данных ограничение или нет. Если не использовать его эквивалент (например, Top).

Я написал это согласно mysql.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...