在进行左连接时选择具有MAX值的项目的ID

时间:2016-06-29 13:24:59

标签: sql sql-server sql-server-2008

数据库中的每个产品都可以有许多修订版。有些产品可能根本没有任何修改。

ProductRevision表包含以下字段:Id,Version,SubmitDate

我试图找出如何根据MAX SubmitDate选择一个名为LatestRevisionId的字段,如果不是修订版,那么该字段将为null

SELECT p.Id, p.Name, p.Price
FROM Product p
LEFT OUTER JOIN ProductRevision pr ON p.Id = pr.ProductId

我必须在我的选择中进行子选择吗?我真的想尝试使用HAVING,但无法弄清楚如何使用左连接。

我尝试将以下内容作为子选择:

(SELECT Id 
 FROM ProductRevision 
 WHERE ProductId=p.Id 
 HAVING SubmitDate=MAX(SubmitDate)
) AS LatestVersionId

请注意我使用的是SQL SERVER 2008

3 个答案:

答案 0 :(得分:1)

以下是使用row_number的一个选项:

SELECT *
FROM (
    SELECT p.Id, p.Name, p.Price, pr.id as LatestRevisionId, 
           row_number() over (partition by p.Id order by pr.SubmitDate desc) rn
    FROM Product p
    LEFT OUTER JOIN ProductRevision pr PN p.Id = pr.ProductId
) t
WHERE rn = 1

这将选择一个Product,其中包含ProductRevision表中最新匹配的行。

如果您只是想使用max,那么您需要再次join该表回复自己:

SELECT p.Id, p.Name, p.Price, pr.id as LatestRevisionId
FROM Product p
LEFT OUTER JOIN ProductRevision pr PN p.Id = pr.ProductId
LEFT OUTER JOIN (SELECT ProductId, MAX(SubmitDate) MaxSubmitDate
                 FROM ProductRevision 
                 GROUP BY ProductId) mpr ON pr.ProductId = mpr.ProductId AND
                                           pr.SubmitDate = mpr.MaxSubmitDate

如果多个版本共享相同的日期,这可能会返回重复项。

答案 1 :(得分:0)

您可以像这样使用SELECT p.Id, p.Name, p.Price, pr.RevisionId as LatestRevisionId FROM Product p LEFT OUTER JOIN (SELECT pr.*, ROW_NUMBER() OVER (PARTITION BY ProductId ORDER BY SubmitDate DESC) as seqnum FROM ProductRevision pr ) ON p.Id = pr.ProductId AND seqnum = 1;

SELECT p.Id, p.Name, p.Price,
       MAX(CASE WHEN seqnum = 1 THEN pr.RevisionId END) as LatestRevisionId
FROM Product p LEFT OUTER JOIN
     (SELECT pr.*,
             ROW_NUMBER() OVER (PARTITION BY ProductId ORDER BY SubmitDate DESC) as seqnum
      FROM ProductRevision pr
     )
     ON p.Id = pr.ProductId
GROUP BY p.Id, p.Name, p.Price;

如果要聚合其他值,请执行以下操作:

def thenReturn[T](target: OngoingStubbing[T], result: Any) = 
  target.thenReturn(result.asInstanceOf[T])

thenReturn(when(myMock.someMethod), myEnumeration)

这应该是完成你想要的最简单的方法。

答案 2 :(得分:0)

如果您使用的是 SQL Server 2012和aboe ,则下面的代码会为您提供所需的结果。

SELECT DISTINCT p.Id, p.Name, p.Price, FIRST_VALUE(pr.ID) OVER (PARTITION BY p.Id ORDER BY pr.SubmitDate DESC) AS LatestVersionId
FROM Product p
LEFT OUTER JOIN ProductRevision pr ON p.Id = pr.ProductId