如何编写SQL SELECT查询:按值筛选及日志表事件筛选逻辑
解决按特征ID筛选SQL日志表的问题
首先,我完全理解你的需求:针对每个feature_id,如果它的最后一条事件是delete,就只保留这条delete记录;否则保留该feature_id的所有记录。咱们可以用两种直观的SQL方案来实现,下面详细拆解:
方案一:分组关联获取最新事件信息
这种方法先定位每个feature_id的最新事件,再通过关联筛选符合规则的记录,逻辑清晰易懂:
WITH latest_events AS ( -- 第一步:找出每个feature_id的最新事件ID(假设event_id随事件递增) SELECT feature_id, MAX(event_id) AS latest_event_id FROM log_table GROUP BY feature_id ), latest_event_details AS ( -- 第二步:关联原表,拿到最新事件的类型 SELECT le.feature_id, lt.event_name AS latest_event_name, le.latest_event_id FROM latest_events le JOIN log_table lt ON le.feature_id = lt.feature_id AND le.latest_event_id = lt.event_id ) -- 第三步:按规则筛选记录 SELECT lt.* FROM log_table lt JOIN latest_event_details led ON lt.feature_id = led.feature_id WHERE -- 如果最新事件是delete,仅保留这条最新记录 (led.latest_event_name = 'delete' AND lt.event_id = led.latest_event_id) -- 否则保留该feature_id的所有记录 OR led.latest_event_name != 'delete';
方案二:窗口函数直接标记排序与最新事件
这种方法用窗口函数一次性给每条记录打上排序标签和所属feature_id的最新事件类型,代码更紧凑:
WITH ranked_events AS ( SELECT *, -- 给每个feature_id的记录按事件ID倒序排名,1代表最新记录 ROW_NUMBER() OVER (PARTITION BY feature_id ORDER BY event_id DESC) AS rn, -- 获取每个feature_id的最后一个事件类型(需指定窗口范围确保拿到全局最后值) LAST_VALUE(event_name) OVER ( PARTITION BY feature_id ORDER BY event_id DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS latest_event_name FROM log_table ) SELECT event_id, event_name, table, feature_id FROM ranked_events WHERE -- 最新事件为delete时,只留排名第一的记录 (latest_event_name = 'delete' AND rn = 1) -- 其他情况保留所有记录 OR latest_event_name != 'delete';
验证示例数据
用你提供的测试数据运行上述SQL,会精准输出预期结果:
event_id event_name table feature_id
4 delete x 5
5 insert x 9
5 update x 9
注意:如果你的日志表是用时间戳而非event_id判断事件顺序,只需把ORDER BY event_id DESC替换成对应的时间字段即可。
内容的提问来源于stack exchange,提问作者barteloma
相关产品推荐
相关产品推荐

