MySQL三表关联查询返回重复结果,求正确查询方案
解决多表关联后的重复数据问题
你当前查询出现重复条目,核心原因是笛卡尔积:summary_count表中C_ID=1有3条记录,Images表中C_ID=1有4条记录,INNER JOIN会将这两个表的所有组合进行匹配,最终生成3×4=12条重复的关联数据。
以下是几种针对不同预期结果的解决方案:
方案1:保留summary_count明细,聚合Images为列表
如果希望每条summary_count记录对应一条CMS基础信息,同时将该C_ID下的所有图片路径合并为单个字段(适合展示场景),可使用字符串聚合函数(不同数据库语法略有差异):
MySQL示例
SELECT cms.*, sc.id, sc.total_cheque, sc.total_amount, GROUP_CONCAT(images.Image SEPARATOR ', ') AS image_list FROM cms INNER JOIN summary_count sc ON sc.C_ID = cms.C_ID INNER JOIN images ON images.C_ID = cms.C_ID GROUP BY cms.user_id, cms.C_ID, cms.B_Name, cms.summary_no, cms.summary_count, sc.id, sc.total_cheque, sc.total_amount;
PostgreSQL示例
SELECT cms.*, sc.id, sc.total_cheque, sc.total_amount, STRING_AGG(images.Image, ', ') AS image_list FROM cms INNER JOIN summary_count sc ON sc.C_ID = cms.C_ID INNER JOIN images ON images.C_ID = cms.C_ID GROUP BY cms.user_id, cms.C_ID, cms.B_Name, cms.summary_no, cms.summary_count, sc.id, sc.total_cheque, sc.total_amount;
执行后会得到3条记录(对应summary_count的3条明细),每条包含CMS信息、summary_count明细,以及所有图片的合并列表。
方案2:保留Images明细,聚合summary_count统计值
如果希望每条图片记录对应一条CMS基础信息,同时展示该C_ID下summary_count的聚合统计(比如总支票数、总金额):
SELECT cms.*, COUNT(sc.id) AS total_summary_records, SUM(sc.total_cheque) AS total_cheque_sum, SUM(sc.total_amount) AS total_amount_sum, images.Img_ID, images.Image FROM cms INNER JOIN summary_count sc ON sc.C_ID = cms.C_ID INNER JOIN images ON images.C_ID = cms.C_ID GROUP BY cms.user_id, cms.C_ID, cms.B_Name, cms.summary_no, cms.summary_count, images.Img_ID, images.Image;
执行后会得到4条记录(对应Images的4条明细),每条包含CMS信息、summary_count的聚合统计,以及单张图片信息。
方案3:分别展示两类明细,避免笛卡尔积
如果需要同时展示summary_count和Images的明细,但不想产生交叉重复,可通过UNION ALL拆分关联逻辑:
-- 获取CMS+summary_count明细 SELECT cms.user_id, cms.C_ID, cms.B_Name, cms.summary_no, cms.summary_count, sc.id AS detail_id, sc.total_cheque, sc.total_amount, NULL AS Img_ID, NULL AS Image, 'summary' AS data_type FROM cms INNER JOIN summary_count sc ON sc.C_ID = cms.C_ID UNION ALL -- 获取CMS+Images明细 SELECT cms.user_id, cms.C_ID, cms.B_Name, cms.summary_no, cms.summary_count, NULL AS detail_id, NULL AS total_cheque, NULL AS total_amount, images.Img_ID, images.Image, 'image' AS data_type FROM cms INNER JOIN images ON images.C_ID = cms.C_ID;
执行后会得到7条记录(3条summary明细+4条图片明细),通过data_type字段可区分记录类型。
方案4:仅获取CMS基础信息+两类数据统计值
如果不需要明细,只需要统计该C_ID下summary_count和Images的记录数量:
SELECT cms.*, (SELECT COUNT(*) FROM summary_count WHERE C_ID = cms.C_ID) AS actual_summary_count, (SELECT COUNT(*) FROM images WHERE C_ID = cms.C_ID) AS image_count FROM cms;
执行后仅返回1条CMS记录,同时包含对应的数据统计结果。
内容的提问来源于stack exchange,提问作者Panthil
相关产品推荐
相关产品推荐

