2009-10-21 26 views
9

Estoy trabajando en algún código/base de datos heredado, y necesito agregar un campo a la base de datos que registrará un número de secuencia relacionado con esa ID (extranjera).MySQL: Agregar columna de secuencia basada en otro campo

datos ejemplo de tabla (actuales):

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

I necesitan añadir una columna ID_secuencia que incrementa separado para cada cuenta, el logro de:

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

Nota que la secuencia está relacionada con la cuenta.

¿Hay alguna manera de lograr esto en SQL, o recurro a un script PHP para hacer el trabajo por mí?

TIA, Kev

Respuesta

6

Este debería funcionar, pero probablemente sea lento:

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; 

He llamado la tabla 'test'; Obviamente, eso debe establecerse correctamente. Debe usar una tabla temporal porque MySQL no le permitirá usar una subselección de la misma tabla que está actualizando.

+0

@tom haigh puede por favor explica cómo funciona esto? – FBP

4

La pregunta es etiquetado como "mysql", así que sí, AUTO_INCREMENT de MySQL puede crear ID secuenciales de GroupWise.
ver http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html:

Para MyISAM y BDB tablas puede especificar AUTO_INCREMENT en una columna secundaria en un índice de múltiples columnas. En este caso, el valor generado para la columna AUTO_INCREMENT se calcula como MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. Esto es útil cuando desea colocar datos en grupos ordenados.

edición: Ejemplo de script php (usando PDO, pero es el mismo juego con el módulo 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"; 
} 

impresiones

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

Gracias por la respuesta. Lo siento, debería haber especificado las tablas son innoDB. ¡Eventualmente fui por la solución de tablas temporales a continuación, pero aprecio la entrada! ¡Aclamaciones! –

+0

Buena solución. Esta es la respuesta correcta. Funciona genial. – SuB

5

crear un disparador:

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

Suponiendo que OP tiene MySQL 5 ... – Ben

+0

Gracias por su respuesta, pero al final fui por la solución de tabla temporal anterior. –

+0

Para cualquier persona que tenga problemas con errores confusos, consulte aquí sobre el uso de delimitadores en el desencadenador: http://stackoverflow.com/questions/5814153/error-in-your-sql-syntax-creating-mysql-trigger – Druckles

Cuestiones relacionadas