18

我的目标是从我的表中删除所有不是分组 CaseKey 的 MAX(recordDate) 的记录。因此,如果我有 3 组 3 个 casekey 的 9 条记录,并且每个 casekey 都有其 3 个日期。我会删除每组的 2 个较低日期并得出 3 个总记录,只有每个剩余的 MAX(recordDate)。

我有以下 SQL 查询:

    DELETE FROM table
    WHERE tableID NOT IN (
    SELECT tableID
    FROM (
    Select MAX(recordDate) As myDate, tableID From table
    Group By CaseKey
    ) As foo
    )

我收到错误:第 3 行出错... 列 'table.tableID' 在选择列表中无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。

显然,我可以将 tableID 添加到我的 Group By 子句,但是该语句的结果不正确并返回所有行,而不是仅返回分组 CaseKeys 的 MAX recordDate。

服务器现在已关闭,但明显的答案是:(WildPlasser 答案的微小调整)

DELETE zt FROM ztable zt
WHERE EXISTS (
    SELECT * FROM ztable ex
    WHERE ex.CaseKey = zt.CaseKey
    AND ex.recordDate > zt.recordDate
);

换句话说,对于zt中的每条记录,运行一个查询,看看同一条记录是否也有记录日期更高的记录。如果是,则 WHERE EXISTS 语句通过并删除该记录,否则 WHERE 语句失败,该记录为其自己的 MAX recordDate。

谢谢你,WildPlasser,感谢我以某种方式搞砸的那种简单化的方法。

4

3 回答 3

24

MAX 有一个特殊属性:没有记录的值高于 max。因此,我们可以删除所有具有相同 CaseKey 但记录日期更高的记录的记录:

DELETE FROM ztable zt
WHERE EXISTS (
    SELECT *
    FROM ztable ex
    WHERE ex.CaseKey = zt.CaseKey
    AND ex.recordDate > zt.recordDate
    );

顺便说一句:上面的查询(以及MAX()版本)假设只有一条具有最大日期的记录。可能有联系。

在平局的情况下,您需要在 where 子句中添加一个额外的字段;作为决胜局。假设TableId可以这样运行,查询将变为:

DELETE FROM ztable zt
WHERE EXISTS (
    SELECT *
    FROM ztable ex
    WHERE ex.CaseKey = zt.CaseKey
    AND (   ex.recordDate > zt.recordDate
        OR (ex.recordDate = zt.recordDate AND ex.TableId > zt.TableId)
        )
    );
于 2013-01-10T19:13:53.353 回答
6

只是表达

从我的表中删除所有不是分组 CaseKey 的 MAX(recordDate) 的记录

在 sql 中作为

DELETE FROM table t1
WHERE t1.recordDate <> 
  (SELECT MAX(recordDate)
   FROM table t2
   WHERE t2.CaseKey = t1.CaseKey)
于 2013-01-10T21:26:26.560 回答
1

您可以对排名> 1的所有记录进行caseKey排名,以仅返回较低的日期。这样你就可以使用你的tableID.

DELETE FROM [table]
WHERE [tableID] IN
  (SELECT
    [sub].[tableID]
  FROM
  (
    SELECT 
      [tableID],
      Rank() OVER (PARTITION BY [caseKey] ORDER BY [recordDate] DESC, [tableID] DESC) AS [rank]
    FROM [table]
  ) AS [sub]
  WHERE [sub].[rank] > 1)
于 2013-01-10T20:19:34.500 回答