Algo como o seguinte deve funcionar:
SELECT ID, Date, Time, Status
from (select ID, Date, Time, Status, row_number() over (order by Date) Ranking
from MyTable
where ID = @SearchId
and Date <= @SearchDate) xx
where Ranking < 3
order by Date, Time
Isso retornará no máximo duas linhas. Não está claro se você está usando colunas com tipos de dados Data e Hora, ou se você está realmente usando palavras reservadas como nomes de colunas, então você terá que se preocupar com isso. (Deixei de fora o Tempo, mas você pode facilmente adicionar isso às várias ordenações e filtragens.)
Dados os critérios revisados, fica um pouco mais complicado, pois a inclusão ou exclusão de uma linha depende do valor retornado em uma linha diferente. Aqui, a “segunda” linha, se houver duas ou mais linhas, é incluída apenas se a “primeira” linha for igual a um determinado valor. A maneira padrão de fazer isso é consultar os dados para obter o valor máximo e, em seguida, consultá-lo novamente enquanto faz referência ao resultado do primeiro conjunto.
No entanto, você pode fazer muitas coisas malucas com row_number. Trabalhe nisso:
SELECT ID, Date, Time, Status
from (select
ID, Date, Time, Status
,row_number() over (partition by case when Date = @SearchDate then 0 else 1 end
order by case when Date = @SearchDate then 0 else 1 end
,Date) Ranking
from MyTable
where ID = @SearchId
and Date <= @SearchDate) xx
where Ranking = 1
order by Date, Time
Você terá que resolver o problema de data/hora, pois isso só funciona com datas.