entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

1voto

Campos calculados con os en tablas mysql

Tengo una tabla donde, entre otros hay tres campos fechas. Fecha1, Fecha2 y Fecha3. También existe un campo situación que puede tener tres valores (P, V o C).
El campo Fecha3 puede ser nulo o no.
Las tres situaciones son las siguientes:
A) El campo Fecha3 es nulo y el campo Fecha2 es superior a la fecha actual. Situación es igual a "P".
B) El campo Fecha3 es nulo y el campo Fecha2 es menor o igual que la fecha actual. Situación es igual a "V".
C) El campo Fecha3 no es nulo. Debe poner en campo situación una "C".

Indicar que debe comparar la fecha actual del equipo donde se use la tabla. Estoy pensando en una pequeña solución web y me gustaría que ese campo situación formará parte del registro.

Agradeciendo vuestra ayuda felices fiestas para todos.

La estructura de la tabla es la siguiente:

EapId INT(11) AUTO_INCREMENT PRIMARY KEY NOT NULL
EapNul BOLEAN
EapNum INT(9)NOT NULL
EapIdCta INT(11) NOT NULL
EapIdSda INT(11) NOT NULL
EapFecha1 DATE NOT NULL
EapFecha2 DATE NOT NULL
EapLibrado VARCHAR(75) NOT NULL
EapFecha3 DATE
EapSituacion CHAR(1)

0voto

Leonardo-Tadei comentado

Lo que querés es que el campo "situación" se calcula en base a estas condiciones para que no exista en la tabla?

El final mencionás la fecha actual del equipo, pero esta fecha no forma parte de tus condiciones en los escenarios A, B o C. Cuál es la comparación con la fecha actual del equipo?

0voto

Jesusgom comentado

Muchas gracias por tu respuesta. Paso a aclararte mejor lo que necesito hacer.

El campo situación si forma parte de la tabla.

Dicho campo puede tener tres valores posibles.

La fecha actual del equipo se compara con Fecha2 si y solo si la Fecha3 tiene un valor nulo.

De forma que si la Fecha3 es nula y la Fecha2 es igual o anterior al día del equipo el valor del campo situación valdrá "V".

Si la Fecha2 es superior a la fecha de hoy del equipo el campo situación tendrá un valor "P".

Por último, si el campo Fecha3 tiene un valor distinto de nulo el campo situación valdrá "C".

Espero que esto aclare más el problema a resolver. Deseo saber cómo hacerlo automáticamente para evitar scripts de actualización y poder emitir una consulta donde no deba calcular nada para hacer un informe más rápido.

He pensado que MySql puede tener en una tabla un campo calculado con condicionales "if" pero no sé cómo generarlo en la creación de la tabla o con una posterior modificación de la misma, he buscado pero no he encontrado nada que me diga cómo puedo hacerlo.

De nuevo muchas gracias por tu interés en ayudarnos.

He ampliado la pregunta dónde he incluido el registro. El último campo que ves es el que debe ser calculado.

2 Respuestas

1voto

Leonardo-Tadei Puntos227320

A ver: si el campo EapSituacion existe, entonces no es un campo calculado.

Se llama campo calculado a un dato que se muestra en una proyección pero que no está almacenado, sino que si valor sale de un cálculo. Un ejemplo típico de esto es el total de una factura, que no se guarda, sino que se calcula sumando la cantidad por el valor de cada item.

El IF que mencionás se puede escribir perfectamente, pero usarlo para mostrar P, V o C implica que el campo EapSituacion no tiene que existir. Podés escribirlo en la query con un IF o un CASE http://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html

Tener el campo calculado, a priori, no te va a dar un pobre rendimiento para hacer informes. Técnicamente hablando no es una justificación para mantener el campo.

Como solución más compleja, podés sí tener el campo EapSituacion y tener un trigger que a cada cambio de la tabla asigne el valor correspondiente. Usar esta alternativa depende mucho de dónde tengas la lógica de la aplicación: si la lógica está implemetnada en la DB, es la mejor solución; pero si la lógica está implementada en el código, usarla implica tener parte en el código y parte en la DB, con lo que es más difícil el posterior matenimiento. Si bien el trigger es más rápido, en una aplicación que tenga menos de 100 peticiones por minuto, no hay diferencia medible.

Una vez que decidas qué camino tomar, podrías escribir otra pregunta con algún detalle que quieras discutir o con algún problema que te esté dando el código.

Saludos cordiales!

1voto

bl4z3r Puntos16850

Como @Leonardo-Tadei menciona, este problema tiene varias soluciones.

  • Con una vista, podes realizar lo que necesitas sin tener la necesidad de tocar la tabla. La consecuencia de esto es que debes hacer la consulta sobre la vista y este no puede ser modificada.
    CREATE VIEW
    <Nombre de la Vista>
    AS
    SELECT
    EapId,
    EapNul,
    EapNum,
    EapIdCta,
    EapIdSda,
    EapFecha1,
    EapFecha2,
    EapLibrado,
    EapFecha3,
    CASE
      WHEN EapFecha2 >= NOW() AND EapFecha3 IS NULL THEN 'P'
      WHEN EapFecha2 < NOW() AND EapFecha3 IS NULL THEN 'V'
      WHEN EapFecha3 IS NOT NULL THEN 'C'
      ELSE NULL
    END AS EapSituacion
    FROM
    <tabla>;
  • Con un disparador sobre la tabla, que, cada vez que se ingresa un registro o se modifica, actualiza el campo EapSituacion.
    CREATE TRIGGER
    <Nombre del disparador>
    ON
    <Nombre de la tabla>
    FOR
    INSERT, UPDATE
    AS
    UPDATE
      <Nombre de la tabla>
    SET
      EapSituacion =
         CASE
            WHEN INSERTED.EapFecha2 >= NOW() AND INSERTED.EapFecha3 IS NULL THEN 'P'
            WHEN INSERTED.EapFecha2 < NOW() AND INSERTED.EapFecha3 IS NULL THEN 'V'
            WHEN INSERTED.EapFecha3 IS NOT NULL THEN 'C'
            ELSE NULL
         END
    WHERE
      EapId = INSERTED.EapId;
  • Con una columna computada/generada. Esta característica es nueva en la versión 5.7 de MySQL y en MariaDB despues de la versión 5.2. Para mas información ver la documentación y sitios anexos.
    CREATE TABLE sales
    ( 
    EapId INT(11) AUTO_INCREMENT PRIMARY KEY NOT NULL,
    EapNul BOLEAN,
    EapNum INT(9)NOT NULL,
    EapIdCta INT(11) NOT NULL,
    EapIdSda INT(11) NOT NULL,
    EapFecha1 DATE NOT NULL,
    EapFecha2 DATE NOT NULL,
    EapLibrado VARCHAR(75) NOT NULL,
    EapFecha3 DATE,
    EapSituacion CHAR(1) NULL AS (CASE
      WHEN INSERTED.EapFecha2 >= NOW() AND INSERTED.EapFecha3 IS NULL THEN 'P'
      WHEN INSERTED.EapFecha2 < NOW() AND INSERTED.EapFecha3 IS NULL THEN 'V'
      WHEN INSERTED.EapFecha3 IS NOT NULL THEN 'C'
      ELSE NULL
    END)
    );

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta