SQL如何将同PICKSLIPNO下两行不同事件的时间拆分为独立列输出
错误原因
你原有语句报错的核心原因是子查询没有和外层的PICKSLIPNO做关联过滤,查询全表时每个子查询都会返回所有符合SUBJECT和时间条件的DATETIME值,返回行数超过1行就会触发子查询返回多条结果的错误。同时你的语句也没有按PICKSLIPNO去重,会输出大量重复行。另外原有语句中SUBJECT LIKE没有加通配符,等价于等值匹配,直接用=性能更优。
推荐解法(条件聚合,性能最优)
这种写法只需要一次扫描表完成统计,不需要多次子查询,同时可以兼容同一个拣货单存在多条同类型事件的场景(可自行选择取最早/最晚的对应时间),示例代码如下:
SELECT PICKSLIPNO, MAX(CASE WHEN SUBJECT = 'Picking Slip Created' THEN DATETIME END) AS PickingDate, MAX(CASE WHEN SUBJECT = 'Order delivered' THEN DATETIME END) AS DeliveryDate FROM SALESORDHIST WHERE DATETIME >= DATEADD(day, -5, GETDATE()) -- 比直接写GETDATE()-5的兼容性更好 AND DATETIME <= GETDATE() AND SUBJECT IN ('Picking Slip Created', 'Order delivered') -- 提前过滤无用数据提升性能 GROUP BY PICKSLIPNO
逻辑说明:
- 先提前过滤最近5天、且
SUBJECT是目标类型的所有记录,减少后续计算量 - 按
PICKSLIPNO分组,保证每行对应一个拣货单号 - 用
CASE判断对应事件类型取时间,配合MAX聚合函数取对应事件的最晚发生时间,如果你需要取最早时间可以换成MIN
子查询写法修正(仅做参考)
如果你坚持要用子查询的写法,需要给内层子查询加上和外层PICKSLIPNO的关联条件,注意如果同一个拣货单存在多条同类型事件,依然会触发多行报错:
SELECT DISTINCT -- 加去重避免同一个拣货单输出多条 o.PICKSLIPNO, ( SELECT DATETIME FROM SALESORDHIST i WHERE i.SUBJECT = 'Picking Slip Created' AND i.DATETIME >= GETDATE()-5 AND i.DATETIME <= GETDATE() AND i.PICKSLIPNO = o.PICKSLIPNO -- 关联外层的拣货单号 ) AS PickingDate, ( SELECT DATETIME FROM SALESORDHIST i WHERE i.SUBJECT = 'Order delivered' AND i.DATETIME >= GETDATE()-5 AND i.DATETIME <= GETDATE() AND i.PICKSLIPNO = o.PICKSLIPNO -- 关联外层的拣货单号 ) AS DeliveryDate FROM SALESORDHIST o WHERE o.DATETIME >= GETDATE()-5 AND o.DATETIME <= GETDATE()
内容的提问来源于stack exchange,提问作者DanOaky
相关产品推荐
相关产品推荐

