1

我有一个events包含用户事件的表,例如:

PK | user | event_type | timestamp
--------------------------------
1  | ab   | DTV        | 1
2  | ab   | DTV        | 2
3  | ab   | CPVR       | 3
4  | cd   | DTV        | 1
5  | cd   | DTV        | 2
6  | cd   | DTV        | 3

我想要做的是每个事件只保留一个事件user,即具有最新timestamp 和的事件event_type = 'DTV'

对上面的示例应用删除后,表格应如下所示:

PK | user | event_type | timestamp
--------------------------------
2  | ab   | DTV        | 2
6  | cd   | DTV        | 3

你们中的任何人都可以想出完成这项任务的方法吗?

更新:我正在使用 Sqlite。这是我到目前为止所拥有的:

delete from events
where id not in (
  select id from (
    select id, user, max(timestamp)
    from events
    where event_type = 'DTV'
    group by user)
);

我很确定这可以改进。有任何想法吗?

4

3 回答 3

3

我认为你应该能够做这样的事情:

delete from events
where (user, timestamp) not in (
    select user, max(timestamp)
    from events
    where event_type = 'DTV'
    group by user
)

您可能会执行一些更复杂的技巧,例如表或分区替换,具体取决于您正在使用的数据库

于 2012-06-04T08:48:05.263 回答
2

如果使用 sql server roo5/2008,则使用以下 sql:

;WITH ce 
     AS (SELECT *, 
                Row_number() 
                  OVER ( 
                    partition BY [user], event_type 
                    ORDER BY timestamp DESC) AS rownumber 
         FROM   emp) 
DELETE FROM ce 
WHERE  rownumber <> 1 
        OR event_type <> 'DTV' 
于 2012-06-04T08:50:29.437 回答
1

在我看来,您的解决方案不够可靠,因为您的子查询正在提取一个既不聚合也不添加到GROUP BY. 我的意思是,我不是一个有经验的 SQLite 用户,你的解决方案在我测试时确实有效。如果有任何确认在这种情况id下列总是与MAX(timestamp)值可靠相关,很好,你的方法似乎相当不错。

但是,如果您和我一样不确定您的解决方案,您可以尝试以下方法:

DELETE FROM events
WHERE NOT EXISTS (
  SELECT *
  FROM (
    SELECT MAX(timestamp) AS ts
    FROM events e
    WHERE event_type = 'DTV'
      AND user = events.user
  ) s
  WHERE ts = events.timestamp
);

的内部实例events被分配了一个不同的别名,以便events可以使用别名来明确引用表的外部实例(DELETE命令实际应用于的那个)。但是,此解决方案确实假定timestampper 是唯一的user

可以在 SQL Fiddle 上运行和使用一个工作示例。

于 2012-06-04T12:00:03.817 回答