Tengo una tabla MySQL con coordenadas, los nombres de columna son X e Y. Ahora quiero intercambiar los valores de columna en esta tabla, de modo que X se convierta en Y e Y se convierta en X. La solución más aparente sería renombrar las columnas, pero yo no quiero hacer cambios en la estructura ya que no necesariamente tengo permisos para hacerlo.
¿Es esto posible hacer con ACTUALIZAR de alguna manera? La tabla ACTUALIZAR SET X = Y, Y = X obviamente no hará lo que quiero.
Editar: Tenga en cuenta que mi restricción de permisos, mencionada anteriormente, impide efectivamente el uso de ALTER TABLE u otros comandos que cambian la estructura de la tabla / base de datos. Desafortunadamente, cambiar el nombre de las columnas o agregar nuevas no son opciones.
UPDATE table SET X = Y, Y = X
es la forma estándar de hacerlo en SQL, solo MySQL se porta mal.Respuestas:
Solo tuve que lidiar con lo mismo y resumiré mis hallazgos.
El
UPDATE table SET X=Y, Y=X
enfoque obviamente no funciona, ya que solo establecerá ambos valores en Y.Aquí hay un método que usa una variable temporal. Gracias a Antony por los comentarios de http://beerpla.net/2009/02/17/swapping-column-values-in-mysql/ por el ajuste "NO ES NULO". Sin ella, la consulta funciona de forma impredecible. Vea el esquema de la tabla al final de la publicación. Este método no intercambia los valores si uno de ellos es NULL. Use el método # 3 que no tiene esta limitación.
UPDATE swap_test SET x=y, y=@temp WHERE (@temp:=x) IS NOT NULL;
Dipin ofreció este método, una vez más, en los comentarios de http://beerpla.net/2009/2009/02/17/swapping-column-values-in-mysql/ . Creo que es la solución más elegante y limpia. Funciona con valores NULL y no NULL.
UPDATE swap_test SET x=(@temp:=x), x = y, y = @temp;
Otro enfoque que se me ocurrió que parece funcionar:
UPDATE swap_test s1, swap_test s2 SET s1.x=s1.y, s1.y=s2.x WHERE s1.id=s2.id;
Esencialmente, la primera tabla es la que se actualiza y la segunda se usa para extraer los datos antiguos.
Tenga en cuenta que este enfoque requiere una clave principal para estar presente.
Este es mi esquema de prueba:
fuente
Puedes tomar la suma y restar el valor opuesto usando X e Y
Aquí hay una prueba de muestra (y funciona con números negativos)
Aquí está el intercambio que se realiza
Darle una oportunidad !!!
fuente
TINYINT
o grandes valores deINT
, ¡tienes razón!El siguiente código funciona para todos los escenarios en mis pruebas rápidas:
fuente
UPDATE table swap_test
? ¿No debería serUPDATE swap_test
?ACTUALIZAR tabla SET X = Y, Y = X hará exactamente lo que desea (editar: en PostgreSQL, no MySQL, ver más abajo) Los valores se toman de la fila anterior y se asignan a una nueva copia de la misma fila, luego se reemplaza la fila anterior. No tiene que recurrir al uso de una tabla temporal, una columna temporal u otros trucos de intercambio.
@ D4V360: Ya veo. Eso es impactante e inesperado. Uso PostgreSQL y mi respuesta funciona correctamente allí (lo probé). Consulte los documentos de ACTUALIZACIÓN de PostgreSQL (en Parámetros, expresión), donde menciona que las expresiones en el lado derecho de las cláusulas SET usan explícitamente los valores antiguos de las columnas. Veo que los documentos de ACTUALIZACIÓN de MySQL correspondientes contienen la declaración "Las asignaciones de ACTUALIZACIÓN de tabla única generalmente se evalúan de izquierda a derecha", lo que implica el comportamiento que usted describe.
Bueno saber.
fuente
Ok, solo por diversión, ¡podrías hacer esto! (suponiendo que está intercambiando valores de cadena)
Un poco divertido abusando del proceso de evaluación de izquierda a derecha en MySQL.
Alternativamente, solo use XOR si son números. Usted mencionó las coordenadas, ¿tiene valores enteros encantadores o cadenas complejas?
Editar: Por cierto, las cosas XOR funcionan así:
fuente
Creo que tener una variable de intercambio intermedia es la mejor práctica de esta manera:
Primero, funciona siempre; segundo, funciona independientemente del tipo de datos.
A pesar de ambos
y
generalmente funcionan, solo para el tipo de datos numéricos, y es su responsabilidad evitar el desbordamiento, no puede usar XOR entre firmado y sin firmar, tampoco puede usar la suma para la posibilidad de desbordamiento.
Y
no funciona si c1 es 0 o NULL o cadena de longitud cero o solo espacios.
Necesitamos cambiarlo a
Aquí están los guiones:
fuente
Dos alternativas 1. Usar una tabla temporal 2. Investigar el algoritmo XOR
fuente
¿Algo como esto?Editar: Sobre el comentario de Greg: No, esto no funciona:
fuente
¡Esto seguramente funciona! Solo lo necesitaba para intercambiar columnas de precios Euro y SKK. :)
Lo anterior no funcionará (ERROR 1064 (42000): tiene un error en su sintaxis SQL)
fuente
Suponiendo que tiene enteros firmados en sus columnas, es posible que necesite usar CAST (a ^ b COMO SE FIRMÓ), ya que el resultado del operador ^ es un entero de 64 bits sin signo en MySQL.
En caso de que ayude a alguien, este es el método que utilicé para intercambiar la misma columna entre dos filas dadas:
donde $ 1 y $ 2 son las claves de dos filas y $ 3 es el resultado de la primera consulta.
fuente
No lo he intentado pero
Podría hacerlo
marca
fuente
Usted podría cambiar los nombres de las columnas, pero esto es más de un truco. Pero tenga cuidado con cualquier índice que pueda estar en estas columnas
fuente
El nombre de la tabla es cliente. los campos son ayb, intercambian un valor por b ;.
ACTUALIZAR SET de cliente a = (@ temp: = a), a = b, b = @temp
Verifiqué que esto funciona bien.
fuente
En SQL Server, puede usar esta consulta:
fuente
Intercambio de valores de columna mediante una sola consulta
ACTUALIZAR my_table SET a = @ tmp: = a, a = b, b = @ tmp;
salud...!
fuente
Solo tenía que mover el valor de una columna a la otra (como archivar) y restablecer el valor de la columna original.
El siguiente (referencia del # 3 de la respuesta aceptada arriba) funcionó para mí.
fuente
fuente
Este ejemplo intercambia start_date y end_date por registros en los que las fechas son incorrectas (al realizar ETL en una reescritura importante, encontré algunas fechas de inicio posteriores a sus fechas de finalización . ¡Abajo, malos programadores!).
In situ, estoy usando MEDIUMINTs por razones de rendimiento (como los días julianos, pero con una raíz 0 de 1900-01-01), así que estaba bien haciendo una condición de WHERE mdu.start_date> mdu.end_date .
Las PK estaban en las 3 columnas individualmente (por razones operativas / de indexación).
fuente
Supongamos que desea intercambiar el valor de nombre y apellido en tb_user.
Lo más seguro sería:
fuente
Puede aplicar a continuación la consulta, funcionó perfecto para mí.
fuente