我有这样的样本数据
ID DATE TIME STATUS
---------------------------------------------
A 01-01-2000 0900 ACTIVE
A 05-02-2000 1000 INACTIVE
A 01-07-2000 1300 ACTIVE
B 01-05-2005 1000 ACTIVE
B 01-08-2007 1050 ACTIVE
C 01-01-2010 0900 ACTIVE
C 01-07-2010 1900 INACTIVE
从上面的数据集中,如果我们只关注ID='A'
,我们会注意到A
最初处于活动状态,然后在05-02-2000
上变为非活动状态,然后在01-07-2000
之前处于非活动状态}。
这意味着A
从05-Feb-2000
到01-July-2000
无效。
我的问题是:
如果我使用(ID=A, Date=01-04-2000)
执行查询,它应该给我
A 05-02-2000 1000 INACTIVE
因为该日期在该数据集中不可用,所以它应该搜索前一个并打印出来
此外,如果我的条件是(ID=A, Date=01-07-2000)
,它不仅应该打印表中存在的值,还应该打印先前的值
A 05-02-2000 1000 INACTIVE
A 01-07-2000 1300 ACTIVE
如果有人能帮我解决这个问题,我真的很感激。我正在尽力解决这个问题。
谢谢大家。
对此有何看法?
AFAQ
答案 0 :(得分:1)
以下内容应该有效:
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
这将最多返回两行。不清楚你是否使用Date和Time数据类型列,或者如果你实际上使用保留字作为列名,那么你将不得不大惊小怪。 (我遗漏了时间,但您可以轻松地将其添加到各种排序和过滤中。)
鉴于修订后的标准,它会变得有点棘手,因为包含或排除行取决于在不同行中返回的值。这里,仅当“第一”行等于特定值时,才包括“第二”行(如果存在两行或更多行)。执行此操作的标准方法是查询数据以获取最大值,然后在引用第一组结果时再次查询数据。
但是,你可以使用row_number做很多棘手的事情。这方面的工作:
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
您必须解决日期/时间问题,因为这只适用于日期。
答案 1 :(得分:0)
基本上,如果在指定日期它是:
,则需要拉一行1)最后一条记录,或
2)最后无效记录。
这两个条件可能匹配同一行以及两个不同的行。
以下是如何在SQL Server 2005 +中实现此逻辑:
WITH ranked AS (
SELECT
ID,
Date,
Time,
Status,
RankOverall = ROW_NUMBER() OVER ( ORDER BY Date DESC),
RankByStatus = ROW_NUMBER() OVER (PARTITION BY Status ORDER BY Date DESC)
FROM Activity
WHERE ID = @ID
AND Date <= @Date
)
SELECT
ID,
Date,
Time,
Status,
FROM ranked
WHERE RankOverall = 1
OR Status = 'INACTIVE' AND RankByStatus = 1