You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL查询优化:用单次JOIN结合CASE语句替代多左连接

解决方案:用单次关联+条件聚合替换多次LEFT JOIN

你的场景属于行转列需求,用单次关联结合条件聚合(CASE+聚合函数)是最优方案之一,性能远优于多次LEFT JOIN,因为只需要扫描Ship_LOG_TIMES一次。

方法1:条件聚合(推荐,兼容性强)

直接关联一次Ship_LOG_TIMES,用CASE配合MAX()(或MIN(),根据你需要取同类型事件的最新/最早时间选择)提取不同类型的时间:

SELECT 
    Orders.ID,
    MAX(CASE WHEN slt.EventType = '1' THEN slt.Event_Time END) AS Invoice_date,
    MAX(CASE WHEN slt.EventType = '2' THEN slt.Event_Time END) AS Est_Ship_date,
    MAX(CASE WHEN slt.EventType = '4' THEN slt.Event_Time END) AS Del_date,
    MAX(CASE WHEN slt.EventType = '5' THEN slt.Event_Time END) AS Return_date
FROM Orders
LEFT JOIN Ship_LOG_TIMES slt ON slt.OrderID = Orders.ID
GROUP BY Orders.ID

关键说明:

  • 用MAX()是因为如果同一个订单对应多个同类型事件(比如多次修改预计发货时间),可以自动取最新的时间;如果每个订单同类型事件只会有一条,MAX()/MIN()效果完全一致
  • 仅需关联一次Ship_LOG_TIMES,大幅减少表扫描次数,数据量越大,性能优势越明显
  • 语法简洁,新增事件类型时只需加一行CASE语句,易维护

方法2:使用SQL Server专属PIVOT语法

如果习惯用更贴合行转列语义的语法,也可以用PIVOT实现,本质和条件聚合性能相当:

SELECT 
    ID,
    [1] AS Invoice_date,
    [2] AS Est_Ship_date,
    [4] AS Del_date,
    [5] AS Return_date
FROM (
    SELECT 
        Orders.ID,
        slt.EventType,
        slt.Event_Time
    FROM Orders
    LEFT JOIN Ship_LOG_TIMES slt ON slt.OrderID = Orders.ID
) AS SourceTable
PIVOT (
    MAX(Event_Time)
    FOR EventType IN ([1], [2], [4], [5])
) AS PivotTable;

关键说明:

  • PIVOT语法更直观,但灵活性不如条件聚合(比如需要动态生成列时更繁琐)
  • 同样只扫描一次Ship_LOG_TIMES,性能与条件聚合持平

方案优势对比

原方案中多次LEFT JOIN会让数据库重复扫描Ship_LOG_TIMES表,数据量较大时IO开销会急剧上升;而上述两种方案仅需扫描一次目标表,执行效率更高,同时代码更简洁易维护。

内容的提问来源于stack exchange,提问作者Wan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 16:37:15