假设我有一个父数据库和子数据库,并且孩子会保留一些父母发生的事情的运行记录:
create table patient (
fullname text not null,
admission_number integer primary key
);
create table history (
note text not null,
doctor text not null,
admission_number integer references patient (admission_number)
);
(只是一个例子,我没有做医疗申请)。
history
将有相同admission_number
的许多记录:
admission_number doctor note
------------------------------------
3456 Johnson Took blood pressure
7828 Johnson EKG 120, temp 99.2
3456 Nichols Drew blood
9001 Damien Discharged patient
7828 Damien Discharged patient with Rx
所以,我的问题是,我如何构建一个查询,让我可以和/或/不搜索patient
记录的注释字段,例如,如果我想查找每个患者的历史包含“血压”和“出院”。
现在我一直在select
上history
按admission_number
分组,将所有注释与group_concat(note)
合并,然后在{{{{}}进行搜索1}},因此:
having
这是有效的,但它使得某些细节非常复杂 - 例如,我希望能够提出诸如“每个患者的历史都包含”血压“和Damien博士的病史说”出院的事情, “在我的基本查询之上建立这样的资格非常混乱。
有没有更好的方法来表达我的基本查询?
答案 0 :(得分:1)
为什么不使用JOIN
操作?
e.g。 考虑到,患者表包含以下数据:
INSERT INTO patient VALUES('Bob', 3456);
INSERT INTO patient VALUES('Mary', 7828);
INSERT INTO patient VALUES('Lucy', 9001);
运行查询:
SELECT DISTINCT p.fullname, p.admission_number FROM patient p
INNER JOIN history h ON p.admission_number = h.admission_number
WHERE note LIKE '%blood pressure%' OR note LIKE '%Discharged%';
得到你:
fullname = Bob
admission_number = 3456
fullname = Lucy
admission_number = 9001
fullname = Mary
admission_number = 7828
并运行以下查询:
SELECT DISTINCT p.fullname, p.admission_number FROM patient p
INNER JOIN history h ON p.admission_number = h.admission_number
WHERE note LIKE '%blood pressure%';
得到你:
fullname = Bob
admission_number = 3456
答案 1 :(得分:1)
我有一些东西 - 使用EXISTS
来构建这些更简洁:
select * from patients where
exists (
select 1 from history where
history.admission_number == patients.admission_number
AND
history.note LIKE '%blood pressure%'
)
AND
exists (
select 1 from history where
history.admission_number == patients.admission_number
AND
history.note LIKE '%discharged%'
AND
history.doctor == 'Damien'
);
那好多了,现在我可以构建非常细粒度的谓词。
答案 2 :(得分:1)
这与您的EXISTS
方法类似,但以不同方式计算子查询。
这可能会更快,也可能不会更快,具体取决于表和索引的组织方式,以及查询的选择性。
SELECT *
FROM patient
WHERE admission_number IN (SELECT admission_number
FROM history
WHERE note LIKE '%blood pressure%')
AND admission_number IN (SELECT admission_number
FROM history
WHERE note LIKE '%discharged%'
AND doctor = 'Damien')
或者,您可以使用compound subquery(计算交叉点一次可能比为每条记录执行IN
两次更快):
SELECT *
FROM patient
WHERE admission_number IN (SELECT admission_number
FROM history
WHERE note LIKE '%blood pressure%'
INTERSECT
SELECT admission_number
FROM history
WHERE note LIKE '%discharged%'
AND doctor = 'Damien')