基于最大值的唯一性,其中并非所有单元格都相同

时间:2009-05-21 05:49:42

标签: sql

假设我的SQL选择中包含以下结果表:

DocumentId        CreationDate       InstanceId
ABC               10th Jan           0c60f4e2-02fc-4244-9ec5-4d259ea5774d
ABC               11th Jan           2168ab5d-d6ca-4db3-90f0-b621d72108b8
BCA               4th Jan            cb7cdf24-b50f-4bd9-b2b5-d58a14793dd8

请注意,InstanceId对于现在返回的每个都不同;它本质上是该表的主键。

如何修改我的选择,以便每DocumentId只返回一行,选择“最新”(由CreationDate确定),确保行上的InstanceId是正确的。

因此上面的示例结果将返回:

DocumentId        CreationDate       InstanceId
ABC               11th Jan           2168ab5d-d6ca-4db3-90f0-b621d72108b8
BCA               4th Jan            cb7cdf24-b50f-4bd9-b2b5-d58a14793dd8

(顺便说一下,对于这个可怕的问题标题感到抱歉,请随意将其更改为更合适的标题)

3 个答案:

答案 0 :(得分:1)

Oracle示例:

SELECT DISTINCT
       DocumentId,
       FIRST_VALUE(CreationDate)
          OVER (PARTITION BY DocumentId
                ORDER BY CreationDate DESC) AS CreationDate,
       FIRST_VALUE(InstanceId)
          OVER (PARTITION BY DocumentId
                ORDER BY CreationDate DESC) AS InstanceId
FROM   mytable;

如果存在具有完全相同CreationDate的重复文档,显然结果将是不确定的。

答案 1 :(得分:1)

这是SQL Server的一个版本。 基本上,您通过DocumentId列对行进行分组并获取max(creationDate),从而将表与表联接起来。使用这两列作为条件获取Code值。 基本上,所需选择的主键是DocumentName和CreationDate。那些唯一(或应该是唯一)标识您要选择的行。为了获得该密钥,我们创建了一个带有select和groupBy子句的第二个(临时)表。我们将该表与原始表一起使用,并使用该信息进行选择。

SELECT
     mt2.DocumentId
    ,mt2.CreationDate
    ,mt1.InstanceId
FROM
    myTable    mt1
    inner join (SELECT 
                     DocumentId  DocumentId
                    ,MAX(CreationDate)  CreationDate
             FROM       
                     myTable
             GROUP BY 
                     DocumentId
               )mt2  on  mt2.DocumentId = mt1.DocumentId 
                     and mt2.CreationDate = mt1.CreationDate
ORDER BY mt2.DocumentId

每个DocumentId的creationDate应该是唯一的,以使查询能够完美运行。如果每个文档每天需要更多条目,则可以考虑降低CreationDate粒度(例如,添加时间组件)

答案 2 :(得分:0)

这适用于大多数数据库:

SELECT
    cur.DocumentId, cur.CreationDate, cur.InstanceId
FROM
    DocumentVersions cur
LEFT OUTER JOIN
    DocumentVersions next
    ON next.DocumentId = cur.DocumentId
    AND next.CreationDate > cur.CreationDate 
WHERE
    next.DocumentId is null

它将Document表与自身连接起来,搜索具有相同id和更高CreationDate的文档。 where语句表示不能找到具有更高日期的文档,有效地过滤每个DocumentId的最新文档。

如果可能有多个具有相同创建日期的文档,您可以选择具有最高InstanceId的文档:

SELECT
    cur.DocumentId, cur.CreationDate, max(cur.InstanceId)
FROM
    DocumentVersions cur
LEFT OUTER JOIN
    DocumentVersions next
    ON next.DocumentId = cur.DocumentId
    AND next.CreationDate > cur.CreationDate 
WHERE
    next.DocumentId is null
GROUP BY
    cur.DocumentId, cur.CreationDate