Набор результатов MariaDB не возвращает правильные результаты - PullRequest
0 голосов
/ 06 февраля 2019

Мне действительно нужна помощь, чтобы выяснить, какой запрос мне нужно выполнить, чтобы получить следующие критерии:

  • Не показывать пациентов с датой ожидания позже, чем сегодня
  • ДонНе показывать пациентов с «окончательной датой» текущего месяца, если только они не могут отложить удержание
  • До 15-го числа текущего месяца не показывать пациентам окончательную дату последнего месяца после 23-го
  • только присутствующие пациенты, назначенные в очередь
  • представляют только «домашнего пациента» своему «домашнему» пользователю

Поля даты и времени: DATETIME

Структура таблицы

patients - id, name, call_back_date, last_service_date, finalized_date, lock_status

queues - id, name, home_user_id, active

1, test, 2, 1

patient_queue - id, queue_id, patient_id

1, 1, 1

user_queue - id, queue_id, user_id, active
1, 1, 1, 1 


SELECT
    pq.patient_id
        FROM patient_queue pq
        INNER JOIN queues q
            ON pq.queue_id = q.id
        INNER JOIN user_queue uq
            ON uq.queue_id = q.id
        INNER JOIN patients p
            ON pq.patient_id = p.id
        WHERE pq.queue_id = (SELECT
            uq.queue_id
        FROM user_queue uq
        WHERE uq.active = TRUE
        AND uq.user_id = 4)
        AND p.lock_status = FALSE
        AND p.member_status = 'Enrolled'
        OR p.member_status = 'Enrollment'
        AND uq.active = TRUE
        AND q.active = TRUE
        AND p.household_id = NULL
        AND p.call_back_date <= NOW()
        OR p.call_back_date = NULL
        AND (NOW() - p.finalized_date) <= 20
        AND p.finalized_date < NOW()
        OR p.call_back_date = NULL
        AND p.finalized_date = NULL
        OR q.home_user_id = 10
        AND p.call_back_date <= NOW()
        OR q.home_user_id = 10
        AND p.call_back_date = NULL
        AND (NOW() - p.finalized_date) <= 20
        AND p.finalized_date < NOW()
        OR q.home_user_id = 10
        AND p.call_back_date = NULL
        AND p.finalized_date = NULL
        ORDER BY IF(p.call_back_date < NOW(), 0, IF(ISNULL(p.last_service_date), 0.5, p.last_service_date));

Результаты, которые я получаю, не в порядке, и если я обновлю запрос, он будет повторяться примерно 5 раз, поэтому я получу идентификатор 2, затем 10, затем 5, затем 6, а затем 32, затемвернуться к 2 и начать все сначала, так что я не знаю, является ли это моей датой обратного вызова, или я передумываю над этим запросом или что?

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Арифметика даты неверна:

(NOW() - p.finalized_date) <= 20

->

p.finalized_date >= NOW() - INTERVAL 20 DAY

или (только на дату разговора, а не на дату / время):

p.finalized_date >= CURDATE() - INTERVAL 20 DAY

Между тем, это нормально:

p.call_back_date <= NOW()  -- meaning that the callback dates is at or before this instant.

И против ИЛИ

a AND b OR c AND d  means  (a AND b) OR (c AND d)

Если вы имели в виду

a AND (b OR c) AND d

тогда вы должны использовать парены.Это очевидно необходимо здесь:

    AND p.call_back_date <= NOW()
    OR p.call_back_date = NULL
    AND ...

->

    AND (p.call_back_date <= NOW()  OR  p.call_back_date = NULL)
    AND ...

IN () - Для ясности измените

    AND (p.member_status = 'Enrolled' OR p.member_status = 'Enrollment')

до

    AND p.member_status IN ('Enrolled', 'Enrollment')

(Нет разницы в производительности и т. д.)

0 голосов
/ 06 февраля 2019

Не полный ответ, но у меня есть несколько возможных улучшений, которые могут подтолкнуть вас к правильному запросу

SELECT pq.patient_id
FROM patient_queue pq
INNER JOIN queues q ON pq.queue_id = q.id
INNER JOIN user_queue uq ON uq.queue_id = q.id
INNER JOIN patients p ON pq.patient_id = p.id

Первая проблема здесь, я не понимаю, почему это должен быть подзапрос,Удалите его и используйте условие WHERE в основном запросе

    WHERE pq.queue_id = (SELECT
        uq.queue_id
    FROM user_queue uq
    WHERE uq.active = TRUE
    AND uq.user_id = 4)

Так что вместо этого

   WHERE uq.active = TRUE
     AND uq.user_id = 4
     AND p.lock_status = FALSE

Здесь вы смешиваете И и ИЛИ без скобок, что, скорее всего, неверно

    AND p.member_status = 'Enrolled'
    OR p.member_status = 'Enrollment'

Должен быть записан как

    AND (p.member_status = 'Enrolled' OR p.member_status = 'Enrollment')

Ниже у вас снова возникает та же проблема с ИЛИ, но мне трудно понять, как их сгруппировать, но поскольку у вас есть OR p.call_back_date = NULL и OR q.home_user_id = 10 несколько разочевидно, вам нужно сгруппировать их, используя круглые скобки

    AND uq.active = TRUE
    AND q.active = TRUE
    AND p.household_id = NULL
    AND p.call_back_date <= NOW()
    OR p.call_back_date = NULL
    AND (NOW() - p.finalized_date) <= 20
    AND p.finalized_date < NOW()
    OR p.call_back_date = NULL
    AND p.finalized_date = NULL
    OR q.home_user_id = 10
    AND p.call_back_date <= NOW()
    OR q.home_user_id = 10
    AND p.call_back_date = NULL
    AND (NOW() - p.finalized_date) <= 20
    AND p.finalized_date < NOW()
    OR q.home_user_id = 10
    AND p.call_back_date = NULL
    AND p.finalized_date = NULL
    ORDER BY IF(p.call_back_date < NOW(), 0, IF(ISNULL(p.last_service_date), 0.5, p.last_service_date));

Может быть уместно, но обратите внимание, что NOW () также включает время, поэтому в зависимости от того, что хранится в столбцах даты, сравнение их с NOW () может не работатькак и ожидалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...