获得由SQL Server两列分组的第一个记录更改时间戳

时间:2017-07-06 15:29:59

标签: 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.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  version     timestamp
(123, 1.5, '2015-03-27 07:21:04')
(234, 1.5, '2016-10-15 23:08:09')
(345, 1.5, '2016-08-02 21:30:00')

我能够通过使用临时表得到这个。我得到每个id和版本的min(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

4 个答案:

答案 0 :(得分:1)

没有CTE或子查询的解决方案:

_ModerationStatus

答案 1 :(得分:1)

这是一个没有任何连接的查询:

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

答案 2 :(得分:0)

您可以使用带有子查询或CTE的窗口函数。请注意,在您的预期输出中,对于ID 123,您没有选择第一个实例...只选择具有最小TIME的实例,而不考虑日期。如果这是你真正想要的,那么你只需要按顺序使用时间部分。即(partition by id order by cast(timestamp as time))

select t.id, t.version, t.timestamp
from
YourTable t
inner join
(select
    id,
    version,
    timestamp,
    row_number() over (partition by id order by timestamp) as rn
from YourTable) x on x.id = t.id and x.timestamp = t.timestamp and x.version = t.version
where x.rn = 1

答案 3 :(得分:0)

尝试

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"