请求编写适配Tableau的SQL:保留SER_NO首次出现记录
解决方案:保留每个SER_NO最早出现的条目
针对你的需求,因为SELECT DISTINCT只能去除所有列完全重复的行,而你的场景是同一SER_NO对应不同日期的条目,所以必须用分组或窗口函数的方式来筛选每个序列号的最早记录。下面给你两种适配Tableau自定义SQL的方案,优先推荐第一种更简洁的窗口函数写法:
方案一:使用窗口函数ROW_NUMBER()(推荐)
这种方法逻辑清晰,代码简洁,大部分主流SQL引擎(包括Tableau支持的)都兼容:
WITH ranked_events AS ( SELECT *, -- 给每个SER_NO的条目按日期升序排名,最早的标记为1 ROW_NUMBER() OVER (PARTITION BY SER_NO ORDER BY EVENT_TS ASC) AS rn FROM ABUS_DW.V_BIQ_R8_QWB_EVENTS WHERE FAC_PROD_FAM_CD IN ('ACOM', 'SCOM', 'LAP', 'RM', 'SCRD') AND DISC_AREA_ID IN (400, 450) AND PROTOTYPE_IND <> 'Y' AND EXT_CPY_STAT <> 'D' AND EVENT_TS >= <Parameters.Start Date> ) SELECT * FROM ranked_events -- 只保留每个SER_NO排名第一的(即最早的)条目 WHERE rn = 1 ORDER BY EVENT_TS;
代码解释:
WITH ranked_events AS (...):创建一个临时数据集,先把符合筛选条件的数据全部取出,同时给每个SER_NO分组内的条目按EVENT_TS从小到大排名PARTITION BY SER_NO:按序列号分组,确保每个序列号的排名独立计算ORDER BY EVENT_TS ASC:分组内按日期升序排列,最早的记录会被标记为rn=1- 最后主查询只取
rn=1的行,就是每个序列号最早出现的完整条目,再按日期排序即可
方案二:子查询关联(兼容老版本SQL引擎)
如果你的SQL环境不支持窗口函数,也可以用子查询先找出每个序列号的最早日期,再关联原表获取完整数据:
SELECT e.* FROM ABUS_DW.V_BIQ_R8_QWB_EVENTS e -- 子查询找出每个符合条件的SER_NO的最早日期 INNER JOIN ( SELECT SER_NO, MIN(EVENT_TS) AS earliest_event_ts FROM ABUS_DW.V_BIQ_R8_QWB_EVENTS WHERE FAC_PROD_FAM_CD IN ('ACOM', 'SCOM', 'LAP', 'RM', 'SCRD') AND DISC_AREA_ID IN (400, 450) AND PROTOTYPE_IND <> 'Y' AND EXT_CPY_STAT <> 'D' AND EVENT_TS >= <Parameters.Start Date> GROUP BY SER_NO ) s ON e.SER_NO = s.SER_NO AND e.EVENT_TS = s.earliest_event_ts -- 再次过滤原表的条件(避免关联到不符合条件的记录) WHERE e.FAC_PROD_FAM_CD IN ('ACOM', 'SCOM', 'LAP', 'RM', 'SCRD') AND e.DISC_AREA_ID IN (400, 450) AND e.PROTOTYPE_IND <> 'Y' AND e.EXT_CPY_STAT <> 'D' AND e.EVENT_TS >= <Parameters.Start Date> ORDER BY e.EVENT_TS;
代码解释:
- 子查询通过
GROUP BY SER_NO和MIN(EVENT_TS)得到每个序列号的最早日期 - 用
INNER JOIN把原表和子查询关联,匹配序列号和对应最早日期的完整记录 - 最后再次添加筛选条件,确保只保留符合要求的数据
为什么SELECT DISTINCT无效?
SELECT DISTINCT会去除所有列值完全相同的重复行,但你的场景中同一SER_NO对应的其他列(比如EVENT_TS)是不同的,所以这些行不会被视为重复,DISTINCT自然无法达到只保留最早记录的效果。
内容的提问来源于stack exchange,提问作者Stevie G
相关产品推荐
相关产品推荐

