MYSQL条件更新表

时间:2015-02-24 22:50:21

标签: mysql sql-update conditional

我正在尝试根据特定条件更新数据库表。这是样本表。

  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

我不清楚如何去做这件事。任何建议/想法......

修改

请注意,如果有两个不同的中间首字母,我也不想更新表格。

我正在努力使数据保持一致。数据中有一些缺失值。因此,主要目的是识别和合并可能类似的多个条目。同时,我们不希望将错误的数据引入表中。此处显示的数据仅包含整个表的几列。还有其他属性使元组独一无二。

3 个答案:

答案 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

*/