使用PostgreSQL数据库:
我有一个调查应用程序,用户可以在其中输入活动并回答有关其活动的问题。调查本身被称为RECALLS_T,输入的事件是EVENTS_T,答案是ANSWERS_T。答案是针对提供的 活动问题的 ,答案存储在中ACTIVITY_QUESTIONS_T,由Lookup(LOOKUP_T)映射。
RECALLS_T
EVENTS_T
ANSWERS_T
ACTIVITY_QUESTIONS_T
LOOKUP_T
然后,我需要运行一个基于事件的报告,其中每一行都是EVENTS_T每次 召回 的事件(所有事件组合为所有召回)。但是,该报告中的 某些列 需要指示某些答案的值,否则这些单元格为NULL。因此,这是一个 列表报告 。
示例(首先是简单的扁平内容,然后是复杂的列表内容):
RecallID | RecallDate | Event |..| WalkAlone | WalkWithPartner |..| ExerciseAtGym 256 | 10-01-19 | Exrcs |..| NULL | NULL |..| yes 256 | 10-01-19 | Walk |..| yes | NULL |..| NULL 256 | 10-01-19 | Eat |..| NULL | NULL |..| NULL 257 | 10-01-19 | Exrcs |..| NULL | NULL |..| yes
我的SQL在基于表格的基于答案的列中具有内部选择,看起来像这样:
select -- Easy flat stuff first r.id as recallid, r.recall_date as recalldate, ... , -- Example of Tabulated Columns: (select l.description from answers_t ans, activity_questions_t aq, lookup_t l where l.id=aq.answer_choice_id and aq.question_id=13 and aq.id=ans.activity_question_id and aq.activity_id=27 and ans.event_id=e.id) as transportationotherintensity, (select l.description from answers_t ans, activity_questions_t aq, lookup_t l where l.id=66 and l.id=aq.answer_choice_id and aq.question_id=14 and aq.id=ans.activity_question_id and ans.event_id=e.id) as commutework, (select l.description from answers_t ans, activity_questions_t aq, lookup_t l where l.id=67 and l.id=aq.answer_choice_id and aq.question_id=14 and aq.id=ans.activity_question_id and ans.event_id=e.id) as commuteschool, (select l.description from answers_t ans, activity_questions_t aq, lookup_t l where l.id=95 and l.id=aq.answer_choice_id and aq.question_id=14 and aq.id=ans.activity_question_id and ans.event_id=e.id) as dropoffpickup,
SQL可以正常工作,并且报表 得以 呈现, 但是性能很差 。我验证了它的质量是成比例的:没有可以解决它的特定项目的魔术子弹。每个内部选择都会导致性能下降。1,000行的结果集需要15秒,但不应超过2-3秒。
请注意,这些 索引 已经存在:
ACTIVITY_QUESTION_ID
EVENT_ID
RECALL_ID
ACTIVITY_ID
QUESTION_ID
ANSWER_CHOICE_ID
这些内部选择是否有我做错的地方?
总结问题,您想使用条件聚合。在PostgreSQL中,您可以使用:
select ans.event_id, max(l.description) filter (where aq.question_id = 13 and aq.activity_id = 27) as transportationotherintensity max(l.description) filter (where l.id = 66 and aq.question_id = 14 and aq.activity_id = 67) as commutework, . . . from activity_questions_t aq join lookup_t l on l.id = aq.answer_choice_id join answers_t ans on aq.id = ans.activity_question_id group by ans.event_id