我有一个名为Objects
的表,其中包含一些文件,例如:
还有另一个表(States
),它保存这些对象的可能状态,如:
还有第三个表(联结表)记录每个对象的每个状态变化。在第三个表(ObjectStates
)中,记录如下:
等
现在,我想要的是获取每个对象及其最新状态(不是状态历史记录)的查询。可以使用cursors
或使用Cross Apply
命令获得此结果。但是,我想知道是否还有其他方法可以从这三个表中获取每个对象的最新状态?因为cursors
是costy。
答案 0 :(得分:3)
使用row_number()
窗口函数...
select *
from
(
select objects.*,
state.state,
objectstates.changedate,
row_number() over (partition by object.objectid order by changedate desc) rn
from
objects
inner join
objectstates
on objects.id = objectstates.objectid
inner join
states
on objectstates.stateid = states.stateid
) v
where rn = 1
例如,如果因为使用SQL 2000而无法使用row_number
,则可以在max/group by
查询中使用联接。
select objects.*,
state.state,
objectstates.changedate,
from
objects
inner join
objectstates
on objects.id = objectstates.objectid
inner join
states
on objectstates.stateid = states.stateid
inner join
(select objectid, max(changedate) as maxdate from objectstates group by objectid) maxstates
on objectstates.objectid=maxstates.objectid
and objectstates.changedate = maxstates.maxdate
答案 1 :(得分:3)
您可以两次加入ObjectStates
表。表格的第一次加入将获得每个max(activedate)
的{{1}}。第二次,您将加入objectid
和objectid
的值,这将获得与该值相关联的max(activedate)
:
state
答案 2 :(得分:-1)
在过去的好时光中,我们只使用了Scalar子查询。
select o.*, (select top(1) s.description
from objectstates os
join states s on s.id = os.state_id
where os.object_id = o.id
order by os.recorded_time desc) last_state
from objects o;
哪个CROSS APPLY替换。要将其扩展到更多字段,必须将其扩展为类似
select *
from (
select o.*, (select top(1) os.id
from objectstates os
where os.object_id = o.id
order by os.recorded_time desc) last_state
from objects o
) x
join objectstates os on os.id = x.last_state
join states s on s.id = os.state_id;
答案 3 :(得分:-1)
您可以使用分区来查找每个Object的最新行,例如
create table #ObjectState
(
Object int NOT NULL,
State int NOT NULL,
TimeStamp datetime NOT NULL
)
INSERT INTO #ObjectState (Object, State, TimeStamp) VALUES (1, 1, '2012-01-01')
INSERT INTO #ObjectState (Object, State, TimeStamp) VALUES (1, 2, '2012-01-02')
INSERT INTO #ObjectState (Object, State, TimeStamp) VALUES (1, 3, '2012-01-03')
INSERT INTO #ObjectState (Object, State, TimeStamp) VALUES (2, 4, '2012-01-01')
INSERT INTO #ObjectState (Object, State, TimeStamp) VALUES (2, 2, '2012-01-02')
select *, ROW_NUMBER() over (partition by Object order by TimeStamp desc) as RowNo from #ObjectState
select InnerSelect.Object, InnerSelect.State, InnerSelect.TimeStamp FROM
(
select *, ROW_NUMBER() over (partition by Object order by TimeStamp desc) as RowNo from #ObjectState
) InnerSelect
where InnerSelect.RowNo = 1
DROP TABLE #ObjectState
给出输出
Object State TimeStamp
1 3 2012-01-03 00:00:00.000
2 2 2012-01-02 00:00:00.000
为最后一次选择