2

假设我有一个父子数据库,并且子子保留了发生在父子身上的事情的一种运行记录:

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记录,例如,如果我想查找历史记录中包含“血压”和“出院”。

现在我一直在selecthistory那个组进行 a admission_number,将所有注释与 a 结合起来group_concat(note)并在 中进行搜索having,因此:

select * from history 
  group by admission_number
  having group_concat(note) like '%blood pressure%' 
     and group_concat(note) like '%discharged';

这行得通,但它使某些详细说明变得非常复杂——例如,我希望能够询问“每个患者的病史包含“血压”并且其与 Damien 医生的病史为“出院”之类的问题,并建立在我的基本查询之上这样的资格非常混乱。

有没有更好的方式来表达我的基本查询?

4

3 回答 3

1

为什么不使用JOIN手术?

例如考虑到,患者表包含以下数据:

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
于 2013-03-06T21:34:29.223 回答
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'
    );

这好多了,现在我可以构造非常细粒度的谓词了。

于 2013-03-06T22:30:25.003 回答
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')

或者,您可以使用复合子查询(计算交集一次可能比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')
于 2013-03-07T08:13:25.490 回答