2009-10-21 6 views
9

Я работаю над некоторым устаревшим кодом/базой данных и вам нужно добавить поле в базу данных, которое будет записывать порядковый номер, связанный с этим (чужим) идентификатором.MySQL: добавить столбец столбцов на основе другого поля

Пример таблицы данных (текущие):

ID  ACCOUNT  some_other_stuff 
1  1   ... 
2  1   ... 
3  1   ... 
4  2   ... 
5  2   ... 
6  1   ... 

мне нужно добавить столбец sequenceid Инкремент отдельно для каждой учетной записи, достижения:

ID  ACCOUNT  SEQ  some_other_stuff 
1  1   1  ... 
2  1   2  ... 
3  1   3  ... 
4  2   1  ... 
5  2   2  ... 
6  1   4  ... 

Следует отметить, что последовательность имеет отношение к ответу.

Есть ли способ, которым я могу достичь этого в SQL, или я прибегаю к скрипту PHP для выполнения этой работы для меня?

ТИА, Кев

ответ

6

Это должен работать, но, вероятно, медленный:

CREATE temporary table seq (id int, seq int); 
INSERT INTO seq (id, seq) 
    SELECT id, 
     (SELECT count(*) + 1 FROM test c 
     WHERE c.id < test.id AND c.account = test.account) as seq 
    FROM test; 

UPDATE test INNER join seq ON test.id = seq.id SET test.seq = seq.seq; 

Я назвал таблицу «test»; очевидно, что нужно правильно установить. Вы должны использовать временную таблицу, потому что MySQL не позволит вам использовать подзаголовок из той же таблицы, которую вы обновляете.

+0

@tom haigh can объясните, как это работает? – FBP

4

вопрос помечаются как "MySQL", да так, auto_increment MySQL может создать GROUPWISE последовательных идентификаторов.
см http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html:

Для MyISAM и BDB таблицы можно указать AUTO_INCREMENT на вторичной колонке индекса в несколько столбцов. В этом случае генерируемое значение для столбца AUTO_INCREMENT вычисляется как MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. Это полезно, если вы хотите поместить данные в упорядоченные группы.

редактировать: Пример PHP скрипт (используя PDO, но это та же игра с php-mysql модулем)

$pdo = new PDO('mysql:host=...;dbname=...', '...', '...'); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

// example table 
$pdo->exec(
    'CREATE TEMPORARY TABLE Foo (
    id int auto_increment, 
    account int, 
    someotherstuff varchar(32), 
    primary key(account,id) 
) engine=MyIsam' 
); 
// insert example data 
$stmt = $pdo->prepare('INSERT INTO Foo (account,someotherstuff) VALUES (?,?)'); 
$stmt->execute(array(1, '1a')); 
$stmt->execute(array(1, '1b')); 
$stmt->execute(array(1, '1c')); 
$stmt->execute(array(2, '2a')); 
$stmt->execute(array(2, '2b')); 
$stmt->execute(array(1, '1d')); 
unset($stmt); 

// query data 
foreach($pdo->query('SELECT account,id,someotherstuff FROM Foo') as $row) { 
    echo $row['account'], ' ', $row['id'], ' ', $row['someotherstuff'], "\n"; 
} 

печатает

1 1 1a 
1 2 1b 
1 3 1c 
2 1 2a 
2 2 2b 
1 4 1d 
+0

Благодарим за отзыв. Извините - я должен был указать указанные таблицы innoDB. В конце концов я пошел на решение temp tables ниже, но по достоинству оценил вход! Ура! – 2009-10-21 13:24:41

+0

Хорошее решение. Это правильный ответ. прекрасно работает. – SuB

5

Создать триггер:

CREATE TRIGGER trg_mytable_bi 
BEFORE INSERT ON mytable 
FOR EACH ROW 
BEGIN 
     DECLARE nseq INT; 
     SELECT COALESCE(MAX(seq), 0) + 1 
     INTO nseq 
     FROM mytable 
     WHERE account = NEW.account; 
     SET NEW.seq = nseq; 
END; 
+0

Предполагая, что у OP есть MySQL 5 ... – Ben

+0

Спасибо за ваш ответ, но в итоге я пошел на временное решение таблицы выше. – 2009-10-21 13:23:36

+0

Для тех, у кого проблемы с запутанными ошибками, см. Здесь об использовании разделителей в триггере: http://stackoverflow.com/questions/5814153/error-in-your-sql-syntax-creating-mysql-trigger – Druckles

Смежные вопросы