В Analytikerna и Lentus мы проводили сбор и систематизацию данных в рамках крупного исследовательского проекта. Этот проект разрабатывается совместно Институтом экологической медицины Karolinska Institutet, Стокгольм и отделением клинических исследований в области старения и психологии университета Южной Калифорнии.
В проекте предусмотрен этап опросов, на котором происходит опрос по телефону всех проживающих в Швеции близнецов старше 65 лет. Близнецы, отвечающие критериям отбора, переходят на следующий этап. На этом этапе желающих участвовать в проекте близнецов посещает врач с медсестрой. Проводятся физические и нейропсихологические исследования, лабораторные анализы, неврологическое обследование, оценка психологического состояния, а также собираются данные по истории семьи. Кроме того, осуществляется сбор информации о медицинских и экологических факторах риска.
Дополнительную информацию о проекте вы можете получить по адресу: http://www.imm.ki.se/TWIN/TWINUKW.HTM
На поздних этапах администрирование проекта осуществляется с помощью web-интерфейса, написанного на Perl и MySQL .
Каждую ночь собранные во время интервью данные заносятся в базу данных MySQL.
Поиск нераспределенных близнецов
Этот запрос определяет, которые из близнецов переходят во второй этап проекта:
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 sceening 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;
Дадим к этому запросу некоторые пояснения:
CONCAT(p1.id, p1.tvab) + 0 AS tvid
Сортируем по взаимосвязи id и tvab в числовом порядке. Прибавление нуля к результату заставляет MySQL обращаться с результатом как с числом.
column id
Определяет пару близнецов. Является ключевым полем всех таблиц.
column tvab
Определяет близнеца в паре. Принимает значение 1 или 2.
column ptvab
Отрицание tvab . Если значение tvab равно 1, значение этого поля - 2, и наоборот. Данное поле облегчает MySQL задачу оптимизации запроса и экономит время ввода данных.
Этот запрос иллюстрирует, помимо всего прочего, сравнение значений одной таблицы с помощью команды JOIN (p1 и p2) . В этом примере таким образом проверяется, не умер ли один из близнецов до достижения им 65-летнего возраста. Если так и произошло, строка не попадает в список возвращаемых.
Все вышеприведенные поля имеются во всех таблицах, в которых хранится относящаяся к близнецам информация. Ключевыми полями для ускорения работы запросов назначены id,tvab (во всех таблицах), а также id,ptvab (person_data) .
На нашем рабочем компьютере (200МГц UltraSPARC) этот запрос возвращает 150-200 строк, и его выполнение занимает менее секунды.
Текущее количество строк в таблицах, использовавшихся выше:
Таблица | Строки | person_data | 71074 | lentus | 5291 | twin_project | 5286 | twin_data | 2012 | informant_data | 663 | harmony | 381 | postal_groups | 100 |
Вывод таблицы состояний пар близнецов
Каждый опрос оканчивается кодом состояния, называющимся event ("событие"). Приведенный здесь запрос выводит данные обо всех парах близнецов, объединенные по полю event . Таблица наглядно показывает, с каким количеством пар близнецов работа полностью завершена, а в каком количестве пар работа с одним близнецом завершена, а с другим - нет и т.п.
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 sceening 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;
8 8 8
| |