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

多次关联同一张表与CASE过滤,哪种SQL写法性能更优?

两种SQL写法的性能对比与逻辑差异分析

首先得先澄清一个关键问题:你给出的两种写法返回的结果集是不一样的!

第一种写法通过两次左连接,会把table_code='case'和table_code='appe'的行合并到同一行(如果对应keyid存在这两类数据的话),最终返回的行数和MainTable一致。

而第二种写法没有分组,会返回多行:每个匹配的ufd行对应一行,其中只有一个字段有值,另一个为空。如果要让第二种写法和第一种逻辑一致,你需要加上GROUP BY,调整后的写法应该是这样:

SELECT
    MAX(CASE WHEN ufd.table_code = 'case' THEN ufd.user_field_data_01 ELSE '' END) AS 会员ID,
    MAX(CASE WHEN ufd.table_code = 'appe' THEN ufd.user_field_data_01 ELSE '' END) AS 申诉ID
FROM MainTable (nolock)
LEFT JOIN ufd (nolock) ON ufd.keyid = MainTable.keyid
GROUP BY MainTable.keyid

接下来我们基于逻辑一致的前提来对比性能和可读性:

性能对比

性能差异主要取决于ufd表的索引情况和数据量:

1. 当ufd表存在合适的索引(推荐场景)

如果ufd表有(keyid, table_code)的复合索引,并且包含user_field_data_01字段(覆盖索引):

  • 第一种写法:两次左连接都会直接走索引查找,精准定位到table_code='case'和table_code='appe'的行,只读取需要的数据,开销极低。
  • 第二种写法(带GROUP BY):会先取出该keyid对应的所有ufd行(包括其他table_code的行,如果有的话),然后进行分组聚合。如果存在大量无关的table_code数据,会读取不必要的行,增加IO和聚合的开销,性能会比第一种差。

2. 当ufd表无合适索引(不推荐场景)

如果没有索引,两种写法都会走表扫描:

  • 第一种写法:两次全表扫描,每次过滤对应table_code,总开销是两次扫描的总和。
  • 第二种写法:一次全表扫描,然后分组聚合,开销是一次扫描加上聚合成本。这种情况下第二种可能略优,但实际生产环境中不会允许无索引的大表这么操作,所以这个场景参考意义不大。

3. 数据量小的场景

如果MainTable和ufd的数据量都很小,两种写法的性能差异几乎可以忽略,数据库优化器会快速处理完所有操作。

可读性对比

你提到第一种写法可读性更强,这点完全正确:

  • 第一种写法通过别名UfdCase、UfdAppe清晰区分不同类型的连接,每个连接的过滤条件明确,后续维护时一眼就能看懂每个字段对应的业务含义。
  • 第二种写法如果需要扩展更多table_code类型,会不断增加CASE分支,SQL语句会变得冗长,尤其是当CASE逻辑更复杂时,可读性会急剧下降。

总结

  • 优先选择第一种写法:在有合适索引的情况下性能更优,同时可读性和可维护性更好。
  • 如果数据量极小,两种写法差异可以忽略;但数据量较大时,第一种的性能优势会很明显。
  • 一定要注意两种写法的逻辑差异,避免出现结果不符合预期的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:09:08