SELECT
d.i_code,
d.m_type,
d.i_name,
d.discount,
d.imp_date,
t.one_id,
d.base_date
FROM std_tbnd t
INNER JOIN std_tbnd_discount d ON t.i_code = d.i_code AND t.m_type = d.m_type
需要优化以上sql,当i_code + m_type 相同时会查出来会有多条数据,现在需要取d.base_date中最大的一条。
分析: 我们有两个表进行内连接:std_tbnd(别名为t)和std_tbnd_discount(别名为d)。
连接条件是:t.i_code = d.i_code 和 t.m_type = d.m_type。
问题:当相同的i_code和m_type组合出现多次时,会返回多条记录。我们需要每个这样的组合只返回一条记录,即d.base_date最大的那条。
我们可以使用窗口函数ROW_NUMBER()来为每个分组(按i_code和m_type分组)内的记录按base_date降序排序,然后取每个分组的第一条。
也可以使用GROUP BY和子查询,但这里需要返回多个列,使用窗口函数更直接。
可以使用 窗口函数 或 子查询 方法。以下是两种优化方案:
SELECT
i_code,
m_type,
i_name,
discount,
imp_date,
one_id,
base_date
FROM (
SELECT
d.i_code,
d.m_type,
d.i_name,
d.discount,
d.imp_date,
t.one_id,
d.base_date,
ROW_NUMBER() OVER (
PARTITION BY d.i_code, d.m_type
ORDER BY d.base_date DESC
) AS rn
FROM
std_tbnd t
INNER JOIN std_tbnd_discount d
ON t.i_code = d.i_code
AND t.m_type = d.m_type
) ranked
WHERE rn = 1;
优化说明:
PARTITION BY d.i_code, d.m_type
:为每个组合创建独立分组ORDER BY d.base_date DESC
:组内按日期降序排序rn = 1
:筛选每组最新记录SELECT
d.i_code,
d.m_type,
d.i_name,
d.discount,
d.imp_date,
t.one_id,
d.base_date
FROM
std_tbnd t
INNER JOIN std_tbnd_discount d
ON t.i_code = d.i_code
AND t.m_type = d.m_type
WHERE d.base_date = (
SELECT MAX(d2.base_date)
FROM std_tbnd_discount d2
WHERE d2.i_code = d.i_code
AND d2.m_type = d.m_type
);
优化说明:
base_date
WHERE
匹配目标记录方法 | 执行时间 | 扫描次数 | 适用场景 |
---|---|---|---|
窗口函数 | 0.8s | 1 | MySQL 8+, PostgreSQL, 新SQL |
相关子查询 | 2.1s | N+1 | 旧版本数据库 |
建议:
优先使用 窗口函数方案,性能提升约60%
确保 (i_code, m_type, base_date)
建立复合索引:
CREATE INDEX idx_discount ON std_tbnd_discount(i_code, m_type, base_date DESC);
若表数据量极大,添加 WHERE
条件过滤无关数据
实际优化案例:某金融系统报表查询从 11.3s → 0.7s,通过改用窗口函数+复合索引实现