连接 2 个表,在另一个表上选择最高值

Posted

技术标签:

【中文标题】连接 2 个表,在另一个表上选择最高值【英文标题】:Joining 2 tables where select highest value on another table 【发布时间】:2018-02-12 07:25:20 【问题描述】:

我正在尝试加入 2 个表,但仅从表 B 中选择 id 最大且表 A 和 B 之间有 2 列匹配的值。

我已经尝试过了,但由于表 2 的值最高,它只选择了 1 行,但我需要显示整个表 A。

WITH CTE AS 
(
    SELECT DocNum, Status 
    FROM TableB 
    WHERE Id = (SELECT MAX(Id) FROM  TableB)
)
SELECT  TableA.DocNum, DocTitle, cte.Status
FROM TableA
INNER JOIN cte 
ON TableA.DocNum = cte.DocNum

下面的例子:

Table A
    Id DocNum  DocTitle
    1  ST-0001 SomeTitle
    2  ST-0002 SomeTitle
    3  ST-0003 SomeTitle
    4  ST-0004 SomeTitle
    5  ST-0005 SomeTitle

Table B
    Id DocNum Status
    1  ST-0001 Incomplete
    2  ST-0001 Complete
    3  ST-0002 Complete
    4  ST-0003 Incomplete
    5  ST-0004 Incomplete
    6  ST-0004 Complete 
    7  ST-0005 Incomplete   

Result
    DocNum DocTitle Status
    ST-0001 SomeTitle Complete  
    ST-0002 SomeTitle Complete  
    ST-0003 SomeTitle Incomplete  
    ST-0004 SomeTitle Complete  
    ST-0005 SomeTitle Incomplete

【问题讨论】:

到目前为止,您是否尝试过任何方法来解决问题? 您使用的是哪个版本的 SQL(例如 mysql、SQL Server 等)?你有没有尝试过? Join,Group by 是解决方案 您是否尝试过在TableB 中使用Order By fieldname Desc 而不是where 条件max id 【参考方案1】:

您可以使用带有 Row_number 的 CTE 从 tableB 中仅获取每个 docNum 具有最大 id 的行,然后加入该 cte。

首先,创建并填充示例表(在您以后的问题中保存我们这一步):

DECLARE @A As Table
(
    Id int,
    DocNum char(7),
    DocTitle varchar(20)
);

DECLARE @B As Table
(
    Id int,
    DocNum char(7),
    [Status] varchar(20)
);

INSERT INTO @A VALUES
(1, 'ST-0001', 'SomeTitle'),
(2, 'ST-0002', 'SomeTitle'),
(3, 'ST-0003', 'SomeTitle'),
(4, 'ST-0004', 'SomeTitle'),
(5, 'ST-0005', 'SomeTitle');

INSERT INTO @B VALUES
(1, 'ST-0001', 'Incomplete'),
(2, 'ST-0001', 'Complete'),
(3, 'ST-0002', 'Complete'),
(4, 'ST-0003', 'Incomplete'),
(5, 'ST-0004', 'Incomplete'),
(6, 'ST-0004', 'Complete'),
(7, 'ST-0005', 'Incomplete');

然后,使用 tableB 中的 row_number 创建 cte:

;WITH CTE AS
(
    SELECT  Id, 
            DocNum, 
            [Status],
            ROW_NUMBER() OVER(PARTITION BY DocNum ORDER BY Id DESC) As Rn
    FROM @B
)

查询:

SELECT A.DocNum, A.DocTitle, CTE.[Status]
FROM @A A 
INNER JOIN CTE ON A.DocNum = CTE.DocNum
WHERE CTE.rn = 1

结果:

DocNum      DocTitle    Status
ST-0001     SomeTitle   Complete  
ST-0002     SomeTitle   Complete  
ST-0003     SomeTitle   Incomplete  
ST-0004     SomeTitle   Complete  
ST-0005     SomeTitle   Incomplete

You can see a live demo on rextester.

【讨论】:

谢谢。如果 TableB 不包含来自 TableA 的 DocNum,是否仍然可以在结果表中显示状态为 Null 或只是空?我需要将原始 TableA 中的所有 DocNum 连同 Found Status 一起保留在 Result 中。 是的,只需将内连接更改为左连接即可。 我试过了,但没有成功。要使用您的示例运行,我从 TableB 中删除了 id(7),并且当我仍然希望它时,结果表不包括 TableA 中的 id(5)。 是的,抱歉,如果您使用左连接,您还应该将CTE.rn = 1 上的条件移动到ON 子句。 here is a rextester example

以上是关于连接 2 个表,在另一个表上选择最高值的主要内容,如果未能解决你的问题,请参考以下文章

在 Max(date) 上选择给定条件的数据

在 Azure SQL 上运行非常缓慢的外部表上选择

在多个表上选择最大值,而不计算两次

在子表上选择查询

在没有唯一键的两个表上选择查询

在单击反应表上选择行