MYSQL 条件更新 table
MYSQL conditional update table
我正在尝试根据特定条件更新数据库 table。这是示例 table.
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
我不清楚该怎么做。任意 suggestions/ideas...
编辑
请注意,如果有两个不同的中间名缩写,我也不想更新 table。
我正在努力使数据保持一致。数据中有一些缺失值。因此,主要目的是识别和合并可能相似的多个条目。同时,我们也不想在table中引入错误的数据。此处显示的数据仅包含整个 table 的几列。还有其他属性使元组独一无二。
使用子选择创建 table 的 "clone" 并更新中间名,加入名字和姓氏。
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;
这是第一个可能的答案。
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
/* 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
*/
我正在尝试根据特定条件更新数据库 table。这是示例 table.
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
我不清楚该怎么做。任意 suggestions/ideas...
编辑
请注意,如果有两个不同的中间名缩写,我也不想更新 table。
我正在努力使数据保持一致。数据中有一些缺失值。因此,主要目的是识别和合并可能相似的多个条目。同时,我们也不想在table中引入错误的数据。此处显示的数据仅包含整个 table 的几列。还有其他属性使元组独一无二。
使用子选择创建 table 的 "clone" 并更新中间名,加入名字和姓氏。
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;
这是第一个可能的答案。
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
/* 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
*/