SQL查询 - 当行首次获得某个值时如何获取

时间:2010-09-16 11:28:06

标签: sql-server tsql sql

我有一个像这样的行的表:

   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 个答案:

答案 0 :(得分:2)

这样的事情:

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

答案 1 :(得分:2)

这个应该能让你得到你想要的东西:

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

当表中只有一条记录或多条记录但状态相同时,我没有包括任何边距示例的检查。你可以自己解决这些问题。

作为单个查询

此查询需要没有间隙的ID,它会在状态更改后获取最后一条记录>当表中只有一条记录或其中多条记录具有相同状态时,它也会起作用( 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 :(得分:0)

尝试

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编写了这个。

答案 3 :(得分:0)

如果表格保证每天有一个条目(根据您的样本数据),则以下内容可能有效

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中的行之间没有任何其他行)

答案 4 :(得分:0)

这是我最终提出的:

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

它正在做我需要它...感谢所有人