我有一张桌子:
ID | CMD_ID | VALUE | CREATED_TIMESTAMP
1 45 'test' 123456
2 46 'news' 123456
3 45 'test' 123457
4 46 'news' 123457
5 45 'TEST' 123468
6 46 'news' 123468
我想一次获取每个CMD_ID,并从最近一次获取该CMD_ID的值更改的时间戳。
如何编写一个SQL查询(用于sqlite),该查询会给我结果:
ID | CMD_ID | VALUE | CREATED_TIMESTAMP
2 46 'news' 123456
5 45 'TEST' 123468
?
到目前为止,我的解决方案是
select * from (select * from test as t where t.id
in (select id from test group by value) order by id desc) group by
cmd_id order by id;
enter code here
这给了我正确答案,但是有没有更有效的方法?
答案 0 :(得分:1)
您需要分组两次,然后加入主表:
select tablename.* from tablename
inner join
(select cmd_id, max(minstamp) as maxstamp from
(select cmd_id, value, min(created_timestamp) as minstamp
from tablename
group by cmd_id, value)
group by cmd_id) as t
on t.cmd_id = tablename.cmd_id and t.maxstamp = tablename.created_timestamp
请参见demo
编辑
在您提供了新案例之后,我想到了这一点:
select tablename.* from tablename inner join (
select t.cmd_id, max(t.created_timestamp) maxstamp from (
select * from (
select
t.*, (
select value from tablename tt
where
tt.cmd_id = t.cmd_id
and
tt.created_timestamp = (
select max(created_timestamp) from tablename
where
cmd_id = t.cmd_id
and
created_timestamp < t.created_timestamp
)
) previousvalue
from tablename t
) t
where
t.previousvalue is null
or
t.value <> t.previousvalue
) t
group by t.cmd_id
) t
on t.cmd_id = tablename.cmd_id and t.maxstamp = tablename.created_timestamp
请参见demo 这次尝试一下。
答案 1 :(得分:0)
在sql服务器中,您可以从中获得最大价值
SELECT ID,来自表GROUP BY ID的最大(时间戳)时间戳
答案 2 :(得分:0)
您可以为此使用row_number
窗口功能。它将为每个记录提供在“分区”(由cmd_id
定义)中具有的序列号。一旦有了该数字作为额外信息,就可以过滤该数字为1的记录:
select id, cmd_id, value, created_timestamp
from (
select test.*,
row_number() over (partition by cmd_id order by created_timestamp desc) rn
from test
)
where rn = 1
答案 3 :(得分:0)
您必须非常小心。假设您有这样的数据:
1 test
2 news
3 test
如果您希望值从“ 1”开始,那么group by
解决方案将起作用。如果要从“ 3”中获得该值,则问题有所不同。问题的表达方式似乎是“ 3”。
SQLite的最新版本支持窗口功能。让我假设您使用的是较早版本。
以下查询通过将0
的值分配给num_different_later
来标识具有相同值的最后一组行:
select t.*,
(select count(*)
from t t2
where t2.cmd_id = t.cmd_id and
t2.created_timestamp > t.created_timestamp and
t2.value <> t.value
) as num_different_after
from t;
我们可以使用聚合来获取最早的时间戳:
select cmd_id, value, min(created_timestamp)
from (select t.*,
(select count(*)
from t t2
where t2.cmd_id = t.cmd_id and
t2.created_timestamp > t.created_timestamp and
t2.value <> t.value
) as num_different_after
from t
) t
where num_different_later = 0;