3.7. Consultas del proyecto Mellizos (Twin)

MySQL 5.0

3.7. Consultas del proyecto Mellizos (Twin)

En Analytikerna y Lentus, hemos estado realizando los sistemas y el trabajo de campo para un gran proyecto de investigación. Este proyecto es en colaboración entre el Institute of Environmental Medicine del Karolinska Institutet Stockholm y la Sección de Investigación Clínica sobre Envejecimiento y Psicología de la Universidad de California del Sur.

El proyecto comprende una parte de selección, en la cual se entrevista por teléfono a todos los gemelos de Suecia mayores de 65 años. Aquellos que satisfacen ciertos criterios son pasados a la siguiente etapa. En esta, los gemelos que desean participar son visitados por un equipo de médico y enfermera. Algunos de los éxamenes practicados son físico, neuropsicológico, laboratorio, diagnóstico neurológico por imágenes, evaluación de estado psicológico, y recolección de la historia familiar. Adicionalmete, se recogen datos sobre factores de riesgo médicos y ambientales.

Se puede ver más información sobre estudio de Gemelos en: http://www.mep.ki.se/twinreg/index_en.html

La última parte del proyecto es administrada mediante una interface Web escrita usando Perl y MySQL.

Cada noche, los datos de las entrevistas son volcados en una base de datos MySQL.

3.7.1. Encontrar todos los mellizos no repartidos

La siguiente consulta es empleada para determinar quiénes pasan a la segunda parte del proyecto:

SELECT
    CONCAT(p1.id, p1.tvab) + 0 AS tvid,
    CONCAT(p1.christian_name, ' ', p1.surname) AS Name,
    p1.postal_code AS Code,
    p1.city AS City,
    pg.abrev AS Area,
    IF(td.participation = 'Aborted', 'A', ' ') AS A,
    p1.dead AS dead1,
    l.event AS event1,
    td.suspect AS tsuspect1,
    id.suspect AS isuspect1,
    td.severe AS tsevere1,
    id.severe AS isevere1,
    p2.dead AS dead2,
    l2.event AS event2,
    h2.nurse AS nurse2,
    h2.doctor AS doctor2,
    td2.suspect AS tsuspect2,
    id2.suspect AS isuspect2,
    td2.severe AS tsevere2,
    id2.severe AS isevere2,
    l.finish_date
FROM
    twin_project AS tp
    /* For Twin 1 */
    LEFT JOIN twin_data AS td ON tp.id = td.id
              AND tp.tvab = td.tvab
    LEFT JOIN informant_data AS id ON tp.id = id.id
              AND tp.tvab = id.tvab
    LEFT JOIN harmony AS h ON tp.id = h.id
              AND tp.tvab = h.tvab
    LEFT JOIN lentus AS l ON tp.id = l.id
              AND tp.tvab = l.tvab
    /* For Twin 2 */
    LEFT JOIN twin_data AS td2 ON p2.id = td2.id
              AND p2.tvab = td2.tvab
    LEFT JOIN informant_data AS id2 ON p2.id = id2.id
              AND p2.tvab = id2.tvab
    LEFT JOIN harmony AS h2 ON p2.id = h2.id
              AND p2.tvab = h2.tvab
    LEFT JOIN lentus AS l2 ON p2.id = l2.id
              AND p2.tvab = l2.tvab,
    person_data AS p1,
    person_data AS p2,
    postal_groups AS pg
WHERE
    /* p1 gets main twin and p2 gets his/her twin. */
    /* ptvab is a field inverted from tvab */
    p1.id = tp.id AND p1.tvab = tp.tvab AND
    p2.id = p1.id AND p2.ptvab = p1.tvab AND
    /* Just the screening survey */
    tp.survey_no = 5 AND
    /* Skip if partner died before 65 but allow emigration (dead=9) */
    (p2.dead = 0 OR p2.dead = 9 OR
     (p2.dead = 1 AND
      (p2.death_date = 0 OR
       (((TO_DAYS(p2.death_date) - TO_DAYS(p2.birthday)) / 365)
        >= 65))))
    AND
    (
    /* Twin is suspect */
    (td.future_contact = 'Yes' AND td.suspect = 2) OR
    /* Twin is suspect - Informant is Blessed */
    (td.future_contact = 'Yes' AND td.suspect = 1
                               AND id.suspect = 1) OR
    /* No twin - Informant is Blessed */
    (ISNULL(td.suspect) AND id.suspect = 1
                        AND id.future_contact = 'Yes') OR
    /* Twin broken off - Informant is Blessed */
    (td.participation = 'Aborted'
     AND id.suspect = 1 AND id.future_contact = 'Yes') OR
    /* Twin broken off - No inform - Have partner */
    (td.participation = 'Aborted' AND ISNULL(id.suspect)
                                  AND p2.dead = 0))
    AND
    l.event = 'Finished'
    /* Get at area code */
    AND SUBSTRING(p1.postal_code, 1, 2) = pg.code
    /* Not already distributed */
    AND (h.nurse IS NULL OR h.nurse=00 OR h.doctor=00)
    /* Has not refused or been aborted */
    AND NOT (h.status = 'Refused' OR h.status = 'Aborted'
    OR h.status = 'Died' OR h.status = 'Other')
ORDER BY
    tvid;

Algunas explicaciones:

  • Se desea ordenar por la concatenación de y en orden numérico. El agregado de al resultado provoca que MySQL lo trate como un número.

  • columna

    Identifica una pareja de gemelos. Es un campo clave en todas las tablas.

  • columna

    Identifica a un gemelo en una pareja. Toma un valor de o .

  • columna

    Es lo inverso de . Cuando . vale , este vale , y viceversa. El motivo de su existencia es para ahorrar tipeo y facilitarle a MySQL la optimización de la consulta.

Esta consulta muestra, entre otras cosas, cómo realizar búsquedas en una tabla a partir de la misma tabla con una unión ( y ). En el ejemplo, esto se usa para verificar cuándo una pareja de gemelos murieron antes de cumplir los 65 años. Si sucede eso, la fila no se devuelve.

Todo lo mencionado anteriormente existe en todas las tablas con información relativa a gemelos. Hay un índice definido sobre los campos (en todas las tablas) y sobre () para realizar las consultas más rápidamente.

En nuestra máquina de producción (un UltraSPARC a 200Mhz), esta consulta devuelve cerca de 150-200 filas y toma menos de un segundo.

La cantidad actual de registros en las tablas usadas en la consulta:

Table Rows
71074
5291
5286
2012
663
381
100

3.7.2. Mostrar una tabla de estado de mellizos

Cada entrevista termina con un código de estado llamado . La consulta mostrada aquí se emplea para mostrar una tabla sobre todas las parejas de gemelos combinadas por evento. Esto indica en cuantas parejas ambos gemelos llegaron al final, en cuantas uno llego y el otro fue rechazado, etc.

SELECT
        t1.event,
        t2.event,
        COUNT(*)
FROM
        lentus AS t1,
        lentus AS t2,
        twin_project AS tp
WHERE
        /* We are looking at one pair at a time */
        t1.id = tp.id
        AND t1.tvab=tp.tvab
        AND t1.id = t2.id
        /* Just the screening survey */
        AND tp.survey_no = 5
        /* This makes each pair only appear once */
        AND t1.tvab='1' AND t2.tvab='2'
GROUP BY
        t1.event, t2.event;