按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