如何将简单的布尔语句转换为SQL?

时间:2010-07-09 13:57:14

标签: sql database join boolean-expression

我有以下数据库表,其中包含有关人员,疾病和药物的信息:

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

从这些表中,我运行了一些关于哪些人服用哪种药物的统计数据 并有哪些疾病。由此我可以找出哪些模式很有趣 我要深入研究。例如,下面是我可能为疾病52找到的布尔模式的简化示例:

( (Drug 234 = false AND Drug 474 = true AND Drug 26 = false) OR 
  (Drug 395 = false AND Drug 791 = false AND Drug 371 = true) )

修改 这是另一个例子:

( (Drug 234 = true AND Drug 474 = true AND Drug 26 = false) OR 
      (Drug 395 = false AND Drug 791 = false AND Drug 371 = true) )

现在我想将此模式转换为sql查询,并找到符合此模式的所有人 例如,我想找到PERSON_T中患有这种疾病的所有人 ((在出现症状之前没有服用药物234和26,但在出现症状之前确实服用了药物474)或 (在出现症状之前服用药物371,但在出现症状之前没服用药物791和395))

我如何将此模式转换回原始查询?

这是我的第一次尝试,但是我在第一个学期遇到困难:

SELECT * FROM PERSON_T, DRUG_T, DISEASE_T 
  WHERE DISEASE_ID = 52 AND 
    PERSON_T.PERSON_ID = DISEASE_T.PERSON_ID AND 
    PERSON_T.PERSON_ID = DRUG_T.PERSON_ID  AND 
    (DRUG_T.DRUG_ID=234 AND (DRUG_T.DRUG_START_DATE>DISEASE_T.END_DATE || ???)

我需要在PostgreSql中使用它,但我认为任何给定的答案都可以从给定的数据库转换为PostgreSql。

对评论的回应

  1. 我修复了数据库的格式 表。谢谢。
  2. 我需要能够获取任意布尔语句并将其转换为SQL。我们实际创建的布尔语句比我给出的示例要长得多。我创建的任何新表都将位于新数据库中,并且需要与原始表具有相同的模式。这种方式对最终用户来说,他们可以在新表上运行相同的代码,它的工作方式与在原始表上运行的相同。这是客户的要求。我希望我可以创建一个只对原始表进行查询的视图。如果我们无法使其工作,我可以创建表的副本并过滤数据,因为我将其复制到新表。我们没有使用神经网络进行分析。我们使用自己的自定义算法,比神经网络更好地扩展。
  3. Disease_Start_Date是患者获得疾病的日期,这可能是症状开始出现的时间。 Disease_End_Date是指症状消失后可能恢复的人。
  4. Drug_start_date是该人开始服用药物的时间。 Drug_end_date是该人停止服用药物的时间。
  5. 修改 我添加了自己的答案。任何人都可以提出一个更简单的答案吗?

10 个答案:

答案 0 :(得分:4)

对我来说,直截了当(如果丑陋)的解决方案是使用EXISTS和NOT EXISTS条款:

SELECT *
FROM PERSON_T INNER JOIN DISEASE_T
     USING (PERSON_ID)
WHERE DISEASE_ID = 52
  AND EXISTS (SELECT 1 FROM DRUG_T
              WHERE DRUG_T.PERSON_ID = PERSON_T.PERSON_ID
                AND DRUG_ID = 474
                AND [time condition])
  AND NOT EXISTS (SELECT 1 FROM DRUG_T
              WHERE DRUG_T.PERSON_ID = PERSON_T.PERSON_ID
                AND DRUG_ID = 234
                AND [time condition])

......等等。在这个例子中,我们要求服用药物474但不服用234的人。显然,你可以根据你的需要将条款与AND和OR分组。

除此之外:我发现很难看到所有的大写字母。我通常对SQL关键字使用大写,对表和列名称使用小写。

答案 1 :(得分:1)

答案 2 :(得分:1)

答案 3 :(得分:0)

请原谅任何错误,但我认为这样的事情会起作用(在T-SQL中):

SELECT col1, col2, col3...
FROM PERSON_T AS P, DRUG_T AS DR, DISEASE_T AS DI
WHERE disease_id = 52
AND P.person_id = DI.person_id
AND P.person_id = DR.person_id
AND drug_id NOT IN(234, 26)
AND drug_id = 474
AND disease_start_date < drug_start_date
UNION
SELECT col1, col2, col3...
FROM PERSON_T AS P, DRUG_T AS DR, DISEASE_T AS DI
WHERE disease_id = 52
AND P.person_id = DI.person_id
AND P.person_id = DR.person_id
AND drug_id NOT IN(791, 395)
AND drug_id = 371
AND disease_start_date < drug_start_date

现在不需要使用UNION,但为了便于阅读,我认为这是最简单的条件。也许这会引导你朝着正确的方向前进。

答案 4 :(得分:0)

SELECT per.person_id, per.name, per.gender
FROM person_t per
INNER JOIN disease_t dis
USING (person_id)
INNER JOIN drug_t drug
USING (person_id)
WHERE dis.disease_id = 52 AND drug.drug_start_date < dis.disease_start_date AND ((drug.drug_id IN (234, 474) AND drug.drug_id NOT IN (26)) OR (drug.drug_id IN (371) AND drug.drug_id NOT IN (395, 791)));

这将满足您的要求。最后的IN语句非常自我解释。

答案 5 :(得分:0)

答案 6 :(得分:0)

答案 7 :(得分:0)

答案 8 :(得分:0)

答案 9 :(得分:0)