我有一个包含用户事件的表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)
);
我很确定这可以改进。有什么想法吗?
答案 0 :(得分:3)
我认为你应该可以做这样的事情:
delete from events
where (user, timestamp) not in (
select user, max(timestamp)
from events
where event_type = 'DTV'
group by user
)
您可能会执行一些更复杂的技巧,例如表格或分区替换,具体取决于您正在使用的数据库
答案 1 :(得分: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'
答案 2 :(得分:1)
您的解决方案在我看来似乎不够可靠,因为您的子查询正在拉动既未汇总也未添加到GROUP BY
的列。我的意思是,我不是一位经验丰富的SQLite用户,而且您的解决方案确实有效when I tested it。如果在这种情况下确认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
命令的实例适用于)。不过,此解决方案确实timestamp
每user
都是唯一的。
可以使用on SQL Fiddle运行并播放工作示例。