我正在尝试根据特定条件更新数据库表。这是样本表。
fname mname lname
1 RONALD D VALE
2 RONALD VALE
3 JACK A SMITH
4 JACK B SMITH
5 JACK SMITH
如果名字和姓氏匹配,我想更新中间名列。在这个例子中,我希望得到以下输出。
fname mname lname
1 RONALD D VALE
2 RONALD D VALE
3 JACK A SMITH
4 JACK B SMITH
5 JACK SMITH
我不清楚如何去做这件事。任何建议/想法......
修改
请注意,如果有两个不同的中间首字母,我也不想更新表格。
我正在努力使数据保持一致。数据中有一些缺失值。因此,主要目的是识别和合并可能类似的多个条目。同时,我们不希望将错误的数据引入表中。此处显示的数据仅包含整个表的几列。还有其他属性使元组独一无二。
答案 0 :(得分:1)
使用子选择来制作表格的“克隆”并更新中间名,加上名字和姓氏。
UPDATE names JOIN
(SELECT fname, mname, lname FROM names WHERE mname IS NOT NULL
GROUP BY fname,mname,lname
HAVING COUNT(*) = 1) AS clone
ON clone.fname = names.fname AND clone.lname=names.lname
SET names.mname = clone.mname;
答案 1 :(得分:1)
这是第一个可能的答案。
UPDATE table t JOIN
( SELECT fname, mname, lname, count(*) as qty
FROM table
GROUP BY fname, lname
HAVING qty > 1
) sub
ON t.fname = sub.fname AND t.lname = sub.lname
SET t.mname = sub.mname
WHERE t.mname = '' and sub.qty = 2
;
<强>更新强>
不应使用CASE WHEN,应使用IF语句。 它处理RONALD VALE记录。
UPDATE table t JOIN
( SELECT fname, mname, min(mname) minname, max(mname) mxname, lname, count(*) as qty
FROM table
GROUP BY fname, lname
HAVING qty > 1
) sub
ON t.fname = sub.fname AND t.lname = sub.lname
SET t.mname = IF(sub.qty = 2, sub.mname, IF(sub.qty > 2, sub.mxname, NULL))
WHERE t.mname is NULL OR LEFT(t.mname,1) = LEFT(sub.mxname, 1)
AND t.mname <> sub.mxname
;
更新2
# Update 1
UPDATE table t JOIN
( SELECT fname, mname, min(mname) minname, max(mname) mxname, lname, count(*) as qty
FROM table
GROUP BY fname, lname
HAVING qty > 1 ) sub ON t.fname = sub.fname AND t.lname = sub.lname SET t.mname = IF(sub.qty = 2, sub.mxname, IF(sub.qty > 2 AND minname = mxname, sub.mxname, NULL)) WHERE t.mname is NULL #OR LEFT(t.mname,1) = LEFT(sub.mxname, 1);
# Update 2
UPDATE table t JOIN
( SELECT fname, mname, min(mname) minname, max(mname) mxname, lname, count(*) as qty
FROM table
GROUP BY fname, lname
HAVING qty > 1 ) sub ON t.fname = sub.fname AND t.lname = sub.lname SET t.mname = IF(sub.qty = 2, sub.mxname, IF(sub.qty > 2, sub.mxname, NULL)) WHERE LEFT(t.mname,1) = LEFT(sub.mxname, 1) AND t.mname <> sub.mxname # reduce unnecessary tasks;
前
DANIEL J ABADI
DANIEL ABADI
DANIEL ABADI
DANIEL ABADI
ROBERT ABADI
ROBERT K ABADI
AMEY S BAILEY
AMEY SCHENCK BAILEY
KARL K KWON
KARL KWON
DINESH MAJETI
ADAM M SMITH
ADAM B SMITH
ADAM C SMITH
ADAM SMITH
ADAM SMITH
JACK A SMITH
JACK B SMITH
JACK SMITH
RONALD A VALE
RONALD D VALE
RONALD DAVID VALE
RONALD VALE
后
DANIEL J ABADI
DANIEL J ABADI
DANIEL J ABADI
DANIEL J ABADI
DANIEL J ABADI
ROBERT K ABADI
ROBERT K ABADI
AMEY SCHENCK BAILEY
AMEY SCHENCK BAILEY
KARL K KWON
KARL K KWON
DINESH MAJETI
ADAM M SMITH
ADAM B SMITH
ADAM C SMITH
ADAM SMITH
ADAM SMITH
JACK A SMITH
JACK B SMITH
JACK SMITH
RONALD A VALE
RONALD DAVID VALE
RONALD DAVID VALE
RONALD VALE
答案 2 :(得分:0)
/* create the table */
CREATE TABLE if not exists `duplicated_names` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(50) DEFAULT NULL,
`middle_name` varchar(50) DEFAULT NULL,
`last_name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `first_name` (`first_name`),
KEY `middle_name` (`middle_name`),
KEY `last_name` (`last_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/* drop old values if any */
truncate duplicated_names ;
/* set up up data for example */
insert into duplicated_names ( first_name, middle_name, last_name ) values ( 'Ronald', 'D', 'Vale') ;
insert into duplicated_names ( first_name, middle_name, last_name ) values ( 'Ronald', 'D', 'Vale') ;
insert into duplicated_names ( first_name, middle_name, last_name ) values ( 'Ronald', '', 'Vale') ;
insert into duplicated_names ( first_name, middle_name, last_name ) values ( 'Jack', 'A', 'Smith') ;
insert into duplicated_names ( first_name, middle_name, last_name ) values ( 'Jack', 'B', 'Smith') ;
insert into duplicated_names ( first_name, middle_name, last_name ) values ( 'Jack', '', 'Smith') ;
update duplicated_names
join (
/* find the middle names */
select duplicated_names.id
, duplicated_names.first_name
, duplicated_names.middle_name
, duplicated_names.last_name
from duplicated_names
inner join (
/* find first_name and last_name that have only one middle name */
select count(*) sum, first_name, last_name from (
/* find candidate middle name donors who have middle names */
select count(*) sum, first_name, middle_name, last_name
from duplicated_names
where middle_name <> ''
group by first_name, middle_name, last_name
) candidate_middle_name_donors
group by first_name, last_name
having count(*) = 1
) names_with_one_middle_name
on names_with_one_middle_name.first_name = duplicated_names.first_name
and names_with_one_middle_name.last_name = duplicated_names.last_name
and duplicated_names.middle_name <> ''
) middle_names
on duplicated_names.first_name = middle_names.first_name
and duplicated_names.last_name = middle_names.last_name
set duplicated_names.middle_name = middle_names.middle_name ;
select * from duplicated_names ;
/*
results
id first_name middle_name last_name
1 Ronald D Vale
2 Ronald D Vale
3 Ronald D Vale
4 Jack A Smith
5 Jack B Smith
6 Jack Smith
*/