0

我的问题很难在标题中解释,所以我将展示数据和目标。有一个具有以下结构的 MySQL 表:

CREATE TABLE customerProjectData(
    idCustomer INT NOT NULL,
    idProject INT DEFAULT NULL,
    comePersons SMALLINT DEFAULT NULL,
    comePairs SMALLINT DEFAULT NULL,
    comment VARCHAR(255) DEFAULT NULL,
    idCity INT DEFAULT NULL,
    idStreet INT DEFAULT NULL,
    name VARCHAR(64) DEFAULT NULL,
    surname VARCHAR(64) DEFAULT NULL,
    homeNum VARCHAR(10) DEFAULT NULL,
    postCode CHAR(6) DEFAULT NULL,
    postCity VARCHAR(64) DEFAULT NULL,
    cellPhone VARCHAR(12) DEFAULT NULL
)

问题是,也应该PRIMARY KEY(idCustomer, idProject)定义,但事实并非如此。结果有一些重复项(具有相同的主键)但具有不同的数据。

我可以跑ALTER IGNORE TABLE,但数据丢失可能是不可接受和不可预测的。最后,我们决定尝试用来自重复项的值填充空字段,如果它们包含数据,然后运行ALTER IGNORE TABLE​​. 这样会丢失更少的数据,并且在这种情况下是可以接受的(这比保留它要好,因为它现在处于较长时间的角度)。

问题是如何从每个重复项中填写这些字段。

4

2 回答 2

1

这是一个粗略的尝试。

首先尝试找出没有。具有相同键的行数。

<?php
// $link is the database identifier

$sql = 'SELECT COUNT(*) AS num, * FROM `customerProjectData` GROUP BY `idCustomer`, `idProject` HAVING COUNT(*) > 1 ORDER BY COUNT(*) ASC;';
$run = mysql_query( $sql, $link );

$rows = array();
if( $run && mysql_num_rows( $run ) ) {
    while( ( $fetch = mysql_fetch_assoc( $run ) ) !== false ) {
        $rows[] = $fetch;
    }
}
?>

现在$rows包含具有相同键的所有行的列表以及count该键在表中重复的次数。

您可以编写一个函数,然后迭代count次数并查看哪些行具有完整的数据,并使用该记录的数据填充其他记录。

一点尝试和错误。

于 2014-03-31T07:38:05.753 回答
0

我使用了@web-nomad 建议并做了类似的事情,但是在 sql 过程中:

DROP PROCEDURE IF EXISTS correctCPD$$
CREATE PROCEDURE correctCPD()
BEGIN

    DECLARE currentCustomerId INT;
    DECLARE currentProjectId INT;
    DECLARE cur_idCustomer INT; 
    DECLARE cur_idProject INT;
    DECLARE cur_comePersons SMALLINT;
    DECLARE cur_comePairs SMALLINT;
    DECLARE cur_comment VARCHAR(255);
    DECLARE cur_idCity INT;
    DECLARE cur_idStreet INT;
    DECLARE cur_name VARCHAR(64);
    DECLARE cur_surname VARCHAR(64);
    DECLARE cur_homeNum VARCHAR(10);
    DECLARE cur_postCode CHAR(6);
    DECLARE cur_postCity VARCHAR(64);
    DECLARE cur_cellPhone VARCHAR(12);

    CREATE TEMPORARY TABLE ids (
        idCustomer INT,
        idProject INT
    ) ENGINE = InnoDB;  

    INSERT INTO ids
        SELECT idCustomer, idProject FROM customerprojectdata group by idCustomer, idProject having count(*) > 1;

    BLOCK1: BEGIN
        DECLARE done INT DEFAULT FALSE;
        DECLARE itemCur CURSOR FOR SELECT idCustomer, idProject FROM ids;   
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

        OPEN itemCur;

        itemCurLoop: LOOP
            FETCH itemCur INTO currentCustomerId, currentProjectId;
            IF done THEN
                LEAVE itemCurLoop;
            END IF;

            BLOCK2: BEGIN
                DECLARE doneIn INT DEFAULT FALSE;   
                DECLARE cpdCur CURSOR FOR SELECT idCustomer, idProject, comePersons, comePairs, comment, idCity, idStreet, name, surname, homeNum, postCode, postCity, cellPhone FROM customerProjectData WHERE idCustomer = currentCustomerId AND idProject = currentProjectId;    
                DECLARE CONTINUE HANDLER FOR NOT FOUND SET doneIn = TRUE;

                OPEN cpdCur;
                cpdCurLoop: LOOP
                    FETCH cpdCur INTO 
                        cur_idCustomer, cur_idProject, cur_comePersons, cur_comePairs, 
                        cur_comment, cur_idCity, cur_idStreet, cur_name, cur_surname, 
                        cur_homeNum, cur_postCode, cur_postCity, cur_cellPhone;
                    IF doneIn THEN
                        LEAVE cpdCurLoop;
                    END IF;

                    UPDATE CustomerProjectData SET 
                        comePersons = IF((comePersons IS NULL OR comePersons = '') AND cur_comePersons > 0, cur_comePersons, comePersons),
                        comePairs = IF((comePairs IS NULL OR comePairs = '') AND cur_comePairs > 0, cur_comePairs, comePairs),
                        comment = IF((comment IS NULL OR comment = '') AND cur_comment > 0, cur_comment, comment),
                        idCity = IF((idCity IS NULL AND idStreet IS NULL) AND cur_idCity > 0, cur_idCity, idCity),
                        idStreet = IF(((idCity IS NULL OR idCity = cur_idCity) AND idStreet IS NULL) AND cur_idStreet > 0, cur_idStreet, idStreet),
                        name = IF((name IS NULL OR name = '') AND cur_name > 0, cur_name, name),
                        surname = IF((surname IS NULL OR surname = '') AND cur_surname > 0, cur_surname, surname),
                        homeNum = IF((homeNum IS NULL OR homeNum = '') AND cur_homeNum > 0, cur_homeNum, homeNum),
                        postCode = IF((postCode IS NULL OR postCode = '') AND cur_postCode > 0, cur_postCode, postCode),
                        postCity = IF((postCity IS NULL OR postCity = '') AND cur_postCity > 0, cur_postCity, postCity),
                        cellPhone = IF((cellPhone IS NULL OR cellPhone = '') AND cur_cellPhone > 0, cur_cellPhone, cellPhone)
                    WHERE idCustomer = currentCustomerId AND idProject = currentProjectId;

                END LOOP;
                CLOSE cpdCur;
            END BLOCK2;
        END LOOP;

        CLOSE itemCur;

    END BLOCK1;

    DROP TEMPORARY TABLE ids;

END$$

感谢帮助!

于 2014-03-31T09:21:24.010 回答