按SQL Server的两列分组时获取第一个记录更改时间戳
我有一个跟踪版本历史记录的表。我需要获取显示第一个版本更改时间戳到最新版本的记录 编辑:添加更多的记录来说明我在寻找什么。 比如说按SQL Server的两列分组时获取第一个记录更改时间戳,sql,sql-server,Sql,Sql Server,我有一个跟踪版本历史记录的表。我需要获取显示第一个版本更改时间戳到最新版本的记录 编辑:添加更多的记录来说明我在寻找什么。 比如说 id version timestamp (123, 1.5, '2015-03-28 08:21:04'), (123, 1.5, '2015-03-28 07:21:04'), (123, 1.5, '2015-03-27 07:21:04'), <-- Latest version,first change for id 123 (123, 1
id version timestamp
(123, 1.5, '2015-03-28 08:21:04'),
(123, 1.5, '2015-03-28 07:21:04'),
(123, 1.5, '2015-03-27 07:21:04'), <-- Latest version,first change for id 123
(123, 1.2, '2015-03-22 12:58:24'),
(123, 1.2, '2015-03-21 13:32:05'),
(123, 1.0, '2015-03-21 09:18:37'),
(123, 1.0, '2015-03-20 04:44:59'),
(234, 1.5, '2016-10-15 23:08:09'), <-- Latest version,first change for id 234
(345, 1.5, '2016-10-10 15:18:09'),
(345, 1.5, '2016-09-02 21:30:00'),
(345, 1.5, '2016-09-01 21:30:00'),
(345, 1.5, '2016-08-02 21:30:00'), <-- Latest version,first change for id 345
(345, 1.0, '2016-07-02 21:30:00')
我可以通过使用临时表来实现这一点。我获取每个id和版本的最小值(dt_create)并将其存储在临时表中。然后从该表中获取每个id的最大日期,然后再次加入该表以获取版本。有更好的方法吗
create table #temp_version
(
id varchar(22) NOT NULL,
version varchar(50) NOT NULL,
dt_create datetime NOT null
)
insert into #temp_version
select id,version,min(dt_create) as dt_create
from [version_history] (nolock)
group by id,version
create table #temp_min_date
(
id varchar(22) NOT NULL,
dt_create datetime NOT null
)
insert into #temp_min_date
select id,max(dt_create)
from #temp_version
group by id
select a.id,a.version,a.dt_create
from #temp_version a
join #temp_date b on a.id = b.id and
a.dt_create=b.dt_create
drop table #temp_date
drop table #temp_version
可以将窗口函数与子查询或CTE一起使用。请注意,在预期的输出中,对于ID 123,您没有选择第一个实例。。。仅限最短时间,不考虑日期。如果这是您真正想要的,那么您只需要使用order by中的时间部分。i、 e.
(按id顺序按类型划分(时间戳为时间))
不带CTE或子查询的解决方案:
SELECT TOP(1) WITH TIES
id,
version,
dt_create = timestamp
FROM [version_history]
ORDER BY ROW_NUMBER() OVER (PARTITION BY id ORDER BY version desc, timestamp)
试一试
下面是一个没有任何联接的查询:
select
id, [version], dt_create
from (
select
id,
[version],
rank() over (partition by id order by [version] desc, dt_create desc) as rnk,
min(dt_create) over (partition by id, [version]) as dt_create
from @history
) res
where
rnk = 1
这里是整个查询和您的测试数据:
declare @history table(id varchar(22), [version] varchar(50), dt_create datetime);
insert into @history(id, [version], dt_create) values
('123', '1.5', '2015-03-28 08:21:04'),
('123', '1.5', '2015-03-28 07:21:04'),
('123', '1.5', '2015-03-27 07:21:04'),
('123', '1.2', '2015-03-22 12:58:24'),
('123', '1.2', '2015-03-21 13:32:05'),
('123', '1.0', '2015-03-21 09:18:37'),
('123', '1.0', '2015-03-20 04:44:59'),
('234', '1.5', '2016-10-15 23:08:09'),
('345', '1.5', '2016-10-10 15:18:09'),
('345', '1.5', '2016-09-02 21:30:00'),
('345', '1.5', '2016-09-01 21:30:00'),
('345', '1.5', '2016-08-02 21:30:00'),
('345', '1.0', '2016-07-02 21:30:00')
select
id, [version], dt_create
from (
select
id,
[version],
rank() over (partition by id order by [version] desc, dt_create desc) as rnk,
min(dt_create) over (partition by id, [version]) as dt_create
from @history
) res
where
rnk = 1
使用
row\u number()
和over()
这是ID 123的最新版本吗?在日期范围中间是正方形的。这对我来说毫无意义me@scsimon1.5是123的最新版本,反映它的第一个时间戳是2015-03-27 07:21:04。这也将在结果中给出123 1.0 2015-03-21 12:58:24.730,因为对于给定的版本,它有一行,并且将得到行号1。如果更改数据,它不起作用,这意味着什么@好奇的思维?我的表有数百万条记录。如果我再添加几条记录,它会给我错误的记录。为了这个(123,1.5,'2015-03-28 08:21:04'),(123,1.5,'2015-03-28 07:21:04'),(123,1.5,'2015-03-27 07:21:04'),(123,1.0,'2015-03-21 12:58:24'),(123,1.2,'2015-03-22 12:58:24'),(123,1.2,',(345, 1.5, '2016-10-10 15:18:09'), (345, 1.5, '2016-09-02 21:30:00'), (345, 1.5, '2016-09-01 21:30:00'), (345, 1.5, '2016-08-02 21:30:00')什么是不正确的?正如我在回答中所解释的,我认为您的预期结果是不正确的。您能解释一下什么是不正确的吗?这不会返回2015-03-21 12:58:24.730
对于Id=123
@Prdp,预期结果中没有这样的值吗?这是一个很好的答案!谢谢,这适用于示例。将测试并更新它。
create table #temp_version
(
id varchar(22) NOT NULL,
version varchar(50) NOT NULL,
dt_create datetime NOT null
)
insert into #temp_version values
(123, 1.5, '2015-03-28 08:21:04'),(123, 1.5, '2015-03-28 07:21:04'),(123, 1.5, '2015-03-27 07:21:04')
,(123, 1.0, '2015-03-21 12:58:24'),(123, 1.0, '2015-03-20 12:58:24'),(123, 1.2, '2015-03-22 12:58:24')
,(123, 1.2, '2015-03-21 12:58:24'),(234, 1.5, '2016-10-15 23:08:09'),(345, 1.5, '2016-10-10 15:18:09')
,(345, 1.5, '2016-09-02 21:30:00'),(345, 1.5, '2016-09-01 21:30:00'),(345, 1.5, '2016-08-02 21:30:00');
select top(1) with ties id, version, dt_create
from (
select *, lag(version) over(partition by id order by dt_create) prev
from #temp_version
) t
where version != prev or prev is null -- first change
-- recent version
order by row_number() over(partition by id order by dt_create desc);
-- or may be .. order by version .. depending on what is "recent"
select
id, [version], dt_create
from (
select
id,
[version],
rank() over (partition by id order by [version] desc, dt_create desc) as rnk,
min(dt_create) over (partition by id, [version]) as dt_create
from @history
) res
where
rnk = 1
declare @history table(id varchar(22), [version] varchar(50), dt_create datetime);
insert into @history(id, [version], dt_create) values
('123', '1.5', '2015-03-28 08:21:04'),
('123', '1.5', '2015-03-28 07:21:04'),
('123', '1.5', '2015-03-27 07:21:04'),
('123', '1.2', '2015-03-22 12:58:24'),
('123', '1.2', '2015-03-21 13:32:05'),
('123', '1.0', '2015-03-21 09:18:37'),
('123', '1.0', '2015-03-20 04:44:59'),
('234', '1.5', '2016-10-15 23:08:09'),
('345', '1.5', '2016-10-10 15:18:09'),
('345', '1.5', '2016-09-02 21:30:00'),
('345', '1.5', '2016-09-01 21:30:00'),
('345', '1.5', '2016-08-02 21:30:00'),
('345', '1.0', '2016-07-02 21:30:00')
select
id, [version], dt_create
from (
select
id,
[version],
rank() over (partition by id order by [version] desc, dt_create desc) as rnk,
min(dt_create) over (partition by id, [version]) as dt_create
from @history
) res
where
rnk = 1