如何使用重复值规范化MySQL表
我有两张水果和颜色的桌子 在水果表中,如何使用重复值规范化MySQL表,mysql,sql,database,Mysql,Sql,Database,我有两张水果和颜色的桌子 在水果表中,cid列引用颜色表中的c_id,但问题是颜色表具有重复的颜色名称: MySQL中是否有一种有效的方法来删除重复的颜色行,并相应地更新foods表中的cid,从而得到如下结果 您可以得到一个结果集,该结果集具有每个f\u id的最小匹配颜色cid SELECT fruit.f_id, fruit.f_name, min(c2.c_id) as c_id FROM fruit INNER JOIN color c1 ON fruit.cid =
cid
列引用颜色表中的c_id
,但问题是颜色表具有重复的颜色名称:
MySQL中是否有一种有效的方法来删除重复的颜色行,并相应地更新foods表中的cid
,从而得到如下结果
您可以得到一个结果集,该结果集具有每个
f\u id的最小匹配颜色cid
SELECT fruit.f_id, fruit.f_name, min(c2.c_id) as c_id
FROM
fruit
INNER JOIN color c1 ON fruit.cid = c1.c_id
INNER JOIN color c2 ON cl.c_name = c2.c_name
GROUP BY fruit.f_id, fruit.f_name
这不是最有效的查询,但它可以工作。您可以使用此选项将水果
表格设置为正确,以便在存在重复项时仅引用单个颜色
修复水果表后,您可以运行查询查看哪些颜色未使用,以便知道要删除的内容:
SELECT color.*
FROM color
LEFT OUTER JOIN fruit on color.c_id = fruit.cid
WHERE fruit.f_id IS NULL
您可以得到一个结果集,其中每个f_id
SELECT fruit.f_id, fruit.f_name, min(c2.c_id) as c_id
FROM
fruit
INNER JOIN color c1 ON fruit.cid = c1.c_id
INNER JOIN color c2 ON cl.c_name = c2.c_name
GROUP BY fruit.f_id, fruit.f_name
这不是最有效的查询,但它可以工作。您可以使用此选项将水果
表格设置为正确,以便在存在重复项时仅引用单个颜色
修复水果表后,您可以运行查询查看哪些颜色未使用,以便知道要删除的内容:
SELECT color.*
FROM color
LEFT OUTER JOIN fruit on color.c_id = fruit.cid
WHERE fruit.f_id IS NULL
您可以通过以下步骤实现此目标-
1。删除重复项-
DELETE FROM colors C1
WHERE EXISTS (SELECT 1
FROM colors C2
WHERE C2.c_name = C1.c_name
AND C2.c_id > C1.c_id);
UPDATE colors C1
JOIN
(
SELECT @rownum:=@rownum+1 rownum, c_id, c_name
FROM colors
CROSS JOIN (select @rownum := 0) rn
) AS C2 ON C1.c_name = C2.c_name
SET C1.c_id = C2.rownum
2。重置c_id-
DELETE FROM colors C1
WHERE EXISTS (SELECT 1
FROM colors C2
WHERE C2.c_name = C1.c_name
AND C2.c_id > C1.c_id);
UPDATE colors C1
JOIN
(
SELECT @rownum:=@rownum+1 rownum, c_id, c_name
FROM colors
CROSS JOIN (select @rownum := 0) rn
) AS C2 ON C1.c_name = C2.c_name
SET C1.c_id = C2.rownum
您可以通过以下步骤实现此目标-
1。删除重复项-
DELETE FROM colors C1
WHERE EXISTS (SELECT 1
FROM colors C2
WHERE C2.c_name = C1.c_name
AND C2.c_id > C1.c_id);
UPDATE colors C1
JOIN
(
SELECT @rownum:=@rownum+1 rownum, c_id, c_name
FROM colors
CROSS JOIN (select @rownum := 0) rn
) AS C2 ON C1.c_name = C2.c_name
SET C1.c_id = C2.rownum
2。重置c_id-
DELETE FROM colors C1
WHERE EXISTS (SELECT 1
FROM colors C2
WHERE C2.c_name = C1.c_name
AND C2.c_id > C1.c_id);
UPDATE colors C1
JOIN
(
SELECT @rownum:=@rownum+1 rownum, c_id, c_name
FROM colors
CROSS JOIN (select @rownum := 0) rn
) AS C2 ON C1.c_name = C2.c_name
SET C1.c_id = C2.rownum
假设表之间存在外键约束,首先需要update
tablefruit
。为此,您可以join
表以获取颜色名称,然后使用相关子查询检索该颜色的最小c_id
:
update fruit f
inner join color c on f.cid = c.c_id
set f.cid = (select min(c_id) from color c1 where c1.name = c.c_name)
然后您可以安全地删除重复的颜色
s,同时保留具有最低c_id的颜色
:
delete c
from color c
inner join color c1 on c1.c_name = c.c_name and c1.c_id < c.c_id
删除c
从c色开始
c1.c_名称上的内部连接颜色c1=c.c_名称和c1.c_id
假设表之间存在外键约束,您首先需要更新
表水果。为此,您可以join
表以获取颜色名称,然后使用相关子查询检索该颜色的最小c_id
:
update fruit f
inner join color c on f.cid = c.c_id
set f.cid = (select min(c_id) from color c1 where c1.name = c.c_name)
然后您可以安全地删除重复的颜色
s,同时保留具有最低c_id的颜色
:
delete c
from color c
inner join color c1 on c1.c_name = c.c_name and c1.c_id < c.c_id
删除c
从c色开始
c1.c_名称上的内部连接颜色c1=c.c_名称和c1.c_id
首先,您需要将水果更新为仅引用每个颜色名称中的一个:
UPDATE fruit AS f
INNER JOIN color As c ON f.cid = c.c_id
INNER JOIN (SELECT c_name, MIN(c_id) AS firstCid FROM color GROUP BY c_name) AS firsts
ON c.c_name = firsts.c_name
SET f.c_id = firsts.firstCid
;
注意:这与GMB的答案类似,但不使用相关子查询
然后,复制品可以用这样的东西清理
DELETE
FROM colors
WHERE c_id NOT IN (
SELECT MIN(c_id)
FROM colors
GROUP BY c_name
)
然而,这也将保留未使用的颜色
MySQL通常不喜欢同时从同一个表中选择和删除的查询,因此它可能必须这样表达才能“欺骗”MySQL:
首先,您需要将水果更新为仅引用每个颜色名称中的一个:
UPDATE fruit AS f
INNER JOIN color As c ON f.cid = c.c_id
INNER JOIN (SELECT c_name, MIN(c_id) AS firstCid FROM color GROUP BY c_name) AS firsts
ON c.c_name = firsts.c_name
SET f.c_id = firsts.firstCid
;
注意:这与GMB的答案类似,但不使用相关子查询
然后,复制品可以用这样的东西清理
DELETE
FROM colors
WHERE c_id NOT IN (
SELECT MIN(c_id)
FROM colors
GROUP BY c_name
)
然而,这也将保留未使用的颜色
MySQL通常不喜欢同时从同一个表中选择和删除的查询,因此它可能必须这样表达才能“欺骗”MySQL:
您可以对删除的每种颜色运行一个查询<代码>更新水果集cid='1',其中cid='7'
,然后从表中删除c_id
7
。对每种颜色重复,直到没有重复,然后不要再重复(使c_name
唯一)。如果是我的话,我会用PHP(我的经验)或其他语言来实现自动化,这将非常简单<代码>更新水果集cid='1',其中cid='7'
,然后从表中删除c_id
7
。对每种颜色重复,直到没有重复,然后不要再重复(使c_name
唯一)。如果是我,我会使用PHP(我的经验)或其他语言来自动完成这项工作,这将非常简单_name@Uueerdo当然有。固定的我想你是想加入c的c1和c2_name@Uueerdo当然有。固定的哎呀,谢谢你!更新查询工作正常,但删除查询抛出错误:“c”在此位置无效,应为:EOF’:“@Csaba:我更新了删除查询,请告诉我它现在是否工作得更好。现在代码看起来有效,但当我执行代码时,我得到:“表'c'被指定了两次,既作为'DELETE'的目标,又作为数据的单独来源”@Csaba:好的,我将其更改为JOIN
ed查询。我对其进行了测试,似乎效果良好。谢谢!更新查询工作正常,但删除查询抛出错误:“c”“在此位置无效,应为:EOF':”@Csaba:我更新了删除查询,请告诉我它现在是否工作得更好。现在代码看起来有效,但当我执行我得到的代码时:“表'c'被指定了两次,既作为'delete'的目标,也作为数据的单独源”@Csaba:好的,我将其更改为JOIN
ed查询。我对它进行了测试,结果似乎很好。如果fruit.cid
有一个带有on-delete级联的外键约束,那么最终会删除很多fruit数据;如果它没有任何约束,像香蕉变黄这样的信息将需要手动复制。如果fruit.cid
有一个带有on delete cascade的外键约束,那么最终将擦除大量水果数据;如果它没有任何约束,像香蕉变黄这样的信息需要手动复制