I have a local implemetation of openmrs version 1.9.7 in a hospital in Kisumu, Kenya. Problem comes when I try to write queries to access the patient data collected from the database for data management purposes due to the complexity of the OpenMrs Database. I am also a little dusty with with sql since I have been off practice for a while but I need the data out asap. The query that I have currently is as below
SELECT p.date_created as date_enrolled, pi.identifier, pi.identifier_type identifier_type ,
pn.given_name,pn.middle_name, pn.family_name, p.person_id, p.gender, p.birthdate, p.death_date,
ob.obs_datetime, cm.name as obs_type, CASE co.datatype_id when '1' then ob.value_numeric
when '2' then (select name from concept_name where concept_id = ob.value_coded limit 1)
when '3' then ob.value_text when '6' then ob.value_datetime when '10' then ob.value_boolean when '13' then ob.value_complex else "N/A" END AS obs_value, e.encounter_datetime
FROM person p JOIN person_name pn ON p.person_id = pn.person_id
JOIN patient_identifier pi ON p.person_id = pi.patient_id
JOIN patient_identifier_type pit ON pit.patient_identifier_type_id = pi.identifier_type
JOIN obs ob ON p.person_id = ob.person_id JOIN encounter e ON e.encounter_id = ob.encounter_id
JOIN concept_name cm ON ob.concept_id = cm.concept_id
JOIN concept co ON ob.concept_id = co.concept_id
JOIN concept_datatype cdt ON cdt.concept_datatype_id = co.datatype_id;
Is there an already existing query used that I can use as a starter and maybe modify to fit my needs? Or rather how best do you advice for me to go through this?
Thanks
You did quite well, considering all the tables involved. This is very complicated SQL because you are mixing header and detail data in a single row. You have 2 fairly large problems here if you want to write something in a single query: 1) concept_name has multiple locales (languages), when I suspect you only want one. Try something like locale='en' to reduce the number of rows. 2) the obs table is EAV (entity-attribute-value), plus as you discovered, different value fields correspond to different datatypes. To deal with this, take a look at MySql's GROUP_CONCAT function. Here is a rough shot at doing your query, though I removed some things to simplify and just to get it to work. It will give you an idea of how to use GROUP_CONCAT, but I punted on the datatype -> value CASE statement :
SELECT p.date_created as date_enrolled,
pi.identifier, pi.identifier_type, pn.given_name,
left(GROUP_CONCAT(ob.obs_datetime, cm.name SEPARATOR '\t'),60) as 'ItemDate|ItemName',
e.encounter_datetime
FROM person p JOIN person_name pn ON p.person_id = pn.person_id
JOIN patient_identifier pi ON p.person_id = pi.patient_id
JOIN patient_identifier_type pit ON pit.patient_identifier_type_id = pi.identifier_type
JOIN obs ob ON p.person_id = ob.person_id
JOIN encounter e ON e.encounter_id = ob.encounter_id
JOIN concept_name cm ON ob.concept_id = cm.concept_id
JOIN concept co ON ob.concept_id = co.concept_id
JOIN concept_datatype cdt ON cdt.concept_datatype_id = co.datatype_id
where cm.locale = 'en'
group by 2 limit 10;
All that said, I don't think the OpenMRS folks would recommend that you keep trying this. Use their reporting tools instead.