我有以下表格:
PERSON_T DISEASE_T DRUG_T
========= ========== ========
PERSON_ID DISEASE_ID DRUG_ID
GENDER PERSON_ID PERSON_ID
NAME DISEASE_START_DATE DRUG_START_DATE
DISEASE_END_DATE DRUG_END_DATE
我想编写一个查询,该查询接受疾病ID的输入,并为数据库中的每个人返回一行,其中包含性别列,是否曾患有该疾病的列,以及列对于每种药物,它指明在感染疾病之前是否服用了这种药物。 I.E. true表示drug_start_date< disease_start_date。 False意味着drug_start_date> disease_start_date或该人从未接受过该特定药物。
我们目前从数据库中提取所有数据并使用Java创建包含所有这些值的2D数组。我们正在研究将此逻辑移入数据库。是否可以创建一个将根据需要返回结果集的查询,或者我是否必须创建存储过程?我们正在使用Postgres,但我认为另一个数据库的SQL答案很容易转换为Postgres。
答案 0 :(得分:3)
根据提供的信息:
SELECT p.name,
p.gender,
CASE WHEN d.disease_id IS NULL THEN 'N' ELSE 'Y' END AS had_disease,
dt.drug_id
FROM PERSON p
LEFT JOIN DISEASE d ON d.person_id = p.person_id
AND d.disease_id = ?
LEFT JOIN DRUG_T dt ON dt.person_id = p.person_id
AND dt.drug_start_date < d.disease_start_date
..但是除了drug_id
列之外,会有很多行看起来重复。
答案 1 :(得分:1)
您基本上希望使用药物创建cross-tab查询。虽然有很多OLAP工具可以做这种事情(在各种其他切片和切割数据中),在传统的SQL中做这样的事情并不容易(而且,一般来说,不可能没有除了最简单的场景之外的所有程序句法。)
使用SQL执行此操作时,实际上有两个选项(更准确地说,您有一个选项,另一个更复杂但更灵活的选项来自它):
CASE
语句,以生成代表每种药物的列。这要求提前知道变量值列表(即药物) 这两个选项基本上做同样的事情,你只是简单易用,易于维护,灵活性在第二个选项。
例如,使用选项1:
select
p.NAME,
p.GENDER,
(case when d.DISEASE_ID is null then 0 else 1 end) as HAD_DISEASE,
(case when sum(case when dr.DRUG_ID = 1 then 1 else 0 end) > 0 then 1 else 0 end) as TOOK_DRUG_1,
(case when sum(case when dr.DRUG_ID = 2 then 1 else 0 end) > 0 then 1 else 0 end) as TOOK_DRUG_2,
(case when sum(case when dr.DRUG_ID = 3 then 1 else 0 end) > 0 then 1 else 0 end) as TOOK_DRUG_3
from PERSON_T p
left join DISEASE_T d on d.PERSON_ID = p.PERSON_ID and d.DISEASE_ID = @DiseaseId
left join DRUG_T dr on dr.PERSON_ID = p.PERSON_ID and dr.DRUG_START_DATE < d.DISEASE_START_DATE
group by p.PERSON_ID, p.NAME, p.GENDER, d.DISEASE_ID
正如你所知道的,当你超出一些潜在价值时,这会变得有点费力。
另一种选择是动态构造此查询。我不知道PostgreSQL及其具有的程序功能(如果有的话),但整个过程将是这样的:
DRUG_ID
值列表以及列CASE
语句之前的所有内容,SQL stuffix(最后一个与药物相关的CASE
语句之后的所有内容)和动态部分< / LI>
CASE
语句来构造动态部分