原正常执行的MySQL查询报错:临时表存在重复键(错误1022)
问题分析与解决方法
错误SQL Error [1022] [23000]: Can't write; duplicate key in table '/tmp/#sql2e02_11_10'的核心原因是:MySQL在创建临时表存储查询中间结果时,自动生成的默认唯一键遇到了重复值。这和你已尝试的磁盘空间、内存参数无关,问题出在查询逻辑或底层数据的重复上。
具体解决步骤
1. 修正分组逻辑,确保分组键唯一
你的子查询中计算marketShare时使用GROUP BY a.name,如果US_asins表中name字段不是唯一值(存在多个id对应同一name的情况),或者关联过程中产生了重复行,会导致临时表的默认唯一键冲突。建议将分组键改为a.id, a.name,利用id的主键唯一性避免重复:
2. 移除子查询中无用的ORDER BY
子查询内的ORDER BY cc DESC不会影响最终结果(除非搭配LIMIT),反而会强制MySQL创建临时表并排序,增加出错概率,直接移除即可。
3. 重构查询,减少嵌套层级
用CTE(公共表表达式)替代嵌套子查询,更直观地控制数据流向,避免不必要的临时表创建:
@set asin = 'B0XXXXXXXX' @set dateAt = '2024-01-31' WITH keyword_stats AS ( SELECT ar.keywordId, k.sterm, TRUNCATE(avg(ar.asinRank),1) asinRank, count(*) cc FROM US_daily_asin_keywords ar INNER JOIN US_keywords k ON k.id = ar.keywordId INNER JOIN reports r ON r.id = ar.reportId INNER JOIN US_asins ua ON ua.id = ar.asinId WHERE ua.name = :asin AND r.endDay > :dateAt GROUP BY ar.keywordId, k.sterm ), market_share_stats AS ( SELECT a.name, TRUNCATE(100 * (count(*) / sum(count(*)) OVER ()), 0) marketShare FROM US_daily_asin_keywords ar INNER JOIN US_asins a ON a.id = ar.asinId INNER JOIN US_keywords k ON k.id = ar.keywordId INNER JOIN reports r ON r.id = ar.reportId WHERE r.endDay > :dateAt GROUP BY a.id, a.name ) SELECT TRUNCATE(avg(dr.rankV), 0) rankKey, ks.sterm, TRUNCATE(avg(ks.asinRank), 1) asinRank, TRUNCATE(avg(ks.cc), 0) cc, mss.marketShare FROM US_daily_ranks dr INNER JOIN keyword_stats ks ON ks.keywordId = dr.keywordId LEFT JOIN market_share_stats mss ON mss.name = :asin GROUP BY ks.sterm ORDER BY cc DESC;
4. 排查底层数据重复
检查US_daily_asin_keywords表是否存在重复的(asinId, keywordId, reportId)组合,这类重复会在关联时放大数据量,导致临时表键冲突:
SELECT COUNT(*), asinId, keywordId, reportId FROM US_daily_asin_keywords GROUP BY asinId, keywordId, reportId HAVING COUNT(*) > 1;
如果存在重复数据,需要清理(比如删除重复行或添加唯一约束)。
内容的提问来源于stack exchange,提问作者MainPawn
相关产品推荐
相关产品推荐

