Как я перевожу простой булев оператор в SQL?

У меня есть следующая таблица базы данных с информацией о людях, болезнях и наркотиках:

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 является датой, когда человек заболел болезнью, которая вероятна, когда symptons начинают появляться. Disease_End_Date - когда человек восстанавливается, который вероятен, когда признаки исчезают.
  4. Drug_start_date - когда человек начинает принимать наркотики. Drug_end_date - когда человек прекращает принимать наркотики.

Редактирование я добавил свой собственный ответ. Кто-либо может придумать более простой ответ?

6
задан Jay Askren 23 July 2010 в 18:14
поделиться

3 ответа

На мой взгляд, прямолинейное (хотя и уродливое) решение - использовать предложения 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 и нижний регистр для имен таблиц и столбцов.

4
ответ дан 17 December 2019 в 02:21
поделиться

Простите за ошибки, но я думаю, что будет работать что-то вроде этого (на 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, но для читабельности я подумал, что это самое простое, учитывая ваши условия. Возможно, это направит вас в правильном направлении.

0
ответ дан 17 December 2019 в 02:21
поделиться
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 в конце довольно понятны.

0
ответ дан 17 December 2019 в 02:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: