SQL实现同name值的列排列插入并避免重复
问题描述
需要实现以下需求:
- 针对同一张表中相同name值的记录,生成该name下所有Id与desc的全排列组合
- 将这些组合插入原表,且必须避免已存在的
(Id, name, desc)重复记录
当前尝试的SQL语句如下,但返回结果包含多余数据,需要调整为INSERT ... SELECT形式完成插入:
Select distinct a.id,a.name,a.desc From table a cross join table b Where a.name = b.name
输入表数据
| Id | name | desc |
|---|---|---|
| 1 | apple | App |
| 1 | apple | Aps |
| 2 | apple | Apl |
| 2 | apple | Ale |
| 2 | apple | Apls |
| 3 | orange | orng |
期望输出(仅apple相关的插入结果生效后)
| Id | name | desc |
|---|---|---|
| 1 | apple | App |
| 1 | apple | Aps |
| 1 | apple | Apl |
| 1 | apple | Ale |
| 1 | apple | Apls |
| 2 | apple | App |
| 2 | apple | Aps |
| 2 | apple | Apl |
| 2 | apple | Ale |
| 2 | apple | Apls |
| 3 | orange | orng |
解决方案
问题分析
原SQL的问题在于直接对全表做CROSS JOIN,会产生大量冗余组合(比如同一Id和自身desc的重复匹配),且没有过滤已存在的记录,导致结果不符合预期。
调整后的INSERT语句
针对apple这个name的场景,最终可用以下SQL实现需求:
INSERT INTO your_table (Id, name, `desc`) SELECT DISTINCT ids.Id, ids.name, descs.`desc` FROM ( -- 提取apple对应的所有唯一Id SELECT DISTINCT Id, name FROM your_table WHERE name = 'apple' ) ids CROSS JOIN ( -- 提取apple对应的所有唯一desc SELECT DISTINCT `desc` FROM your_table WHERE name = 'apple' ) descs -- 过滤掉表中已存在的(Id, name, desc)组合 WHERE NOT EXISTS ( SELECT 1 FROM your_table t WHERE t.Id = ids.Id AND t.name = ids.name AND t.`desc` = descs.`desc` );
逻辑说明
- 两个子查询分别提取指定name下的唯一Id集合和唯一desc集合,避免重复数据参与交叉连接
- 通过
CROSS JOIN生成Id与desc的全排列组合 - 利用
NOT EXISTS子查询排除原表中已存在的组合,确保插入的都是缺失的记录
扩展:针对所有name的通用版本
如果需要对表中所有name都执行该逻辑,只需去掉子查询中的WHERE name = 'apple'条件即可:
INSERT INTO your_table (Id, name, `desc`) SELECT DISTINCT ids.Id, ids.name, descs.`desc` FROM ( SELECT DISTINCT Id, name FROM your_table ) ids CROSS JOIN ( SELECT DISTINCT `desc`, name FROM your_table ) descs WHERE ids.name = descs.name AND NOT EXISTS ( SELECT 1 FROM your_table t WHERE t.Id = ids.Id AND t.name = ids.name AND t.`desc` = descs.`desc` );
内容的提问来源于stack exchange,提问作者RR8422
相关产品推荐
相关产品推荐

