3.7. 在 Twin Project项目中查找数据
在 Analytikerna 和 Lentus,我们曾经为一个大的研究项目做过系统和现场工作。这个项目是 Karolinska Institutet Stockholm的环境医学协会 和南加里佛利亚大学的关于年龄和心理的临床研究所合作的。
这个项目先对在瑞典的所有大于65 岁的双胞胎做电话访问, 如果某对双胞胎符合某些条件,则进行下一个步骤,如果这对双胞胎愿意参与这个项目,则派出一个由医生和护士组成的小队对其进行拜访,进行一些身体或精神上的检查、实验室检查、脑电图和心理状态评估, 并且收集家族史。此外,还对医学和环境的危险度信息进行收集。
关于双胞胎研究项目的更多信息,请访问:http://www.mep.ki.se/twinreg/index_en.html
这个项目的后续部分就是使用一个使用Perl 和MySQL开发的Web接口来管理数据。
每天晚上,所有新的访问数据将被添加到 MySQL 数据库中。
3.7.1. 寻找所有未分开的双胞胎
下面的查询可以确定 哪些人可以进行这个项目的第二部分。
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;
说明如下:
-
CONCAT(p1.id, p1.tvab) + 0 AS tvid
我们希望对
id
和tvab
连接后的结果按数值排序, 给结果加上0是为了使 MySQL 把这个结果当成数值。 -
id
列这是每一对双胞胎的标识, 在所有的表中这都是一个键。
-
tvab
列表示每一对双胞胎中的一个,它的值可以是
1
或2
。 -
ptvab
列这个列的值和
tvab
列的值相反,当tvab列的值为1
时这列的值就为2
, 反之亦然。这一列之所以存在是因为可以减少敲键盘的次数,还可以使 MySQL 优化查询。
在这个查询实例中,演示了怎样从到一个同样的表的连接中查找数据 (p1
和p2
),在这里,这种技巧用来确定一对双胞胎是否在 65岁以前就死了,如果是,这一行就不返回。
上述所有信息都存在于所有表中, 我们同时使用id,tvab
键 (所有表),和id,ptvab
键(person_data
表) 来使查询更快。
在我们专用的机器上 (A 200MHz UltraSPARC),这个查询返回 150-200行数据,只需要不到一秒钟。
上面查询的表的当前记录是:
Table | Rows |
person_data |
71074 |
lentus |
5291 |
twin_project |
5286 |
twin_data |
2012 |
informant_data |
663 |
harmony |
381 |
postal_groups |
100 |
3.7.2. 显示一个表示每一对双胞胎状态的表
每一次访问以一个称为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 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;
3.8. 在Apache中使用 MySQL
你可以从 MySQL 数据库中验证用户信息 ,也可以把日志写入 MySQL 表中。
你可以改变Apache的日志格式 以便于MySQL阅读,通过把下面的语句写入Apache的配置文件中:
LogFormat "\"%h\",%{%Y%m%d%H%M%S}t,%>s,\"%b\",\"%{Content-Type}o\", \"%U\",\"%{Referer}i\",\"%{User-Agent}i\""
要把一个日志文件按上面的格式载入到 MySQL中,你可以使用如下语句:
LOAD DATA INFILE '/local/access_log
' INTO TABLEtbl_name
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'
这个表格必须先被创建,还要包含对应的列来能够容纳LogFormat
格式的数据。
相濡以沫,不如相忘于江湖