SQL Server:根据两个表中的特定列获取最新记录

时间:2017-08-10 06:30:12

标签: sql-server

我有两张表具有相同的表格设计。

tblSpeaker1

prop

tblSpeaker2

---------------------
|ID|Speaker |Version|
|--+--------+-------|
|B1|Xiong   |1      |
|B1|Ling    |2      |
|B1|Juyng   |4      |
|G4|Micre   |1      |
|G4|Pyong   |2      |
|Y1|Mong    |2      |
---------------------

我想要实现的是根据版本号获取每个ID的最新记录,但不包含版本列。

目前,我有这个问题:

---------------------
|ID|Speaker |Version|
|--+--------+-------|
|B1|Looke   |3      |
|G4|Chui    |3      |
|G4|Kyui    |4      |
|Y1|Druke   |1      |
---------------------

但它只会返回:

SELECT TOP 1 ID, Speaker 
FROM
    (SELECT * FROM tblSpeaker1
     UNION
     SELECT * FROM tblSpeaker2)
ORDER BY Version

这应该是输出

-------------
|ID|Speaker |
|--+--------|
|B1|Juyng   |
-------------

请帮帮我。谢谢。

3 个答案:

答案 0 :(得分:3)

这是您要使用PARTITION BY的情况。我举一个例子如下:

declare @tblSpeaker1 table
(
id char(2),
speaker varchar(10),
version int
) 
declare @tblSpeaker2 table
(
id char(2),
speaker varchar(10),
version int
) 

insert into @tblSpeaker1 VALUES
('B1','Xiong',1),
('B1','Ling',2),
('B1','Juyng',4),
('G4','Micre',1),
('G4','Pyong',2),
('Y1','Mong',2)

insert into @tblSpeaker2 VALUES
('B1','Looke',3),
('G4','Chui',3),
('G4','Kyui',4),
('Y1','Druke',1)

SELECT id, speaker FROM
(select id, speaker, version, 
ROW_NUMBER() OVER (PARTITION BY id ORDER BY version DESC) as rn from
(select id, speaker, version FROM @tblSpeaker1
union
select id, speaker, version FROM @tblSpeaker2) u) r
WHERE r.rn = 1

这样你就能明白这里发生了什么。首先,您需要UNION这两个表(正如您所做的那样)。接下来,我们使用row_number()函数结合partition by来获取id的编号,以及版本desc上的顺序。最后,我们采用行号为1的值。

答案 1 :(得分:1)

    declare @tbResult table  (ID varchar(2), Speaker varchar(50))
declare @IDTables table (idx int identity(1,1), ID varchar(20))
declare @Counter int
declare @Categories int
declare @Speakers table (ID varchar(2), Speaker varchar(50), Version int)

set @Counter = 1

insert into @Speakers 
select ID, Speaker, Version from tblSpeaker1
insert into @Speakers 
select ID, Speaker, Version from tblSpeaker2

insert into @IDTables
select distinct ID from tblSpeaker1
union 
select distinct ID from tblSpeaker2

set @Categories = (select count(ID) from @IDTables)

while (@Counter <= @Categories)
begin
    declare @ID varchar(2)
    set @ID = (Select ID from @IDTables where idx = @Counter)

    insert into @tbResult
    select top 1 ID, Speaker from @Speakers
    where ID = @ID order by Version Desc

    set @Counter = @Counter + 1
end


select * from @tbResult

答案 2 :(得分:1)

使用OVER子句:

WITH united AS
(
    SELECT *
        FROM (VALUES ('B1', 'Xiong', 1),
                     ('B1', 'Ling', 2),
                     ('B1', 'Juyng', 4),
                     ('G4', 'Micre', 1),
                     ('G4', 'Pyong', 2),
                     ('Y1', 'Mong', 2)) AS tblSpeaker1(ID, Speaker, Version)
    UNION
    SELECT *
        FROM (VALUES ('B1', 'Looke', 3),
                     ('G4', 'Chui', 3),
                     ('G4', 'Kyui', 4),
                     ('Y1', 'Druke', 1)) AS tblSpeaker2(ID, Speaker, Version)
),
numbered AS
(
    SELECT *, row_number() OVER(PARTITION BY ID ORDER BY Version desc) rn 
        FROM united
)
SELECT ID, Speaker
    FROM numbered
    WHERE rn = 1;

输出:

ID   Speaker
---- -------
B1   Juyng
G4   Kyui
Y1   Mong