Выполнение проверки в запросе SQL (может быть, подзапрос?) - PullRequest
0 голосов
/ 23 октября 2018

У меня есть простая система бронирования для тестирования портативных компьютеров с 6 ноутбуками, названными Laptop01 до 06, у каждого из которых есть три выделенных временных интервала.

Пользователь может выбрать эти временные интервалы, если слот не зарезервирован илиесли бронирование было отменено / отклонено.

Пока у меня есть рабочий код, я обнаружил фатальную ошибку, которая приводит к дублированию отмененного / отклоненного слота.

Позвольте мне объяснить ...

Database Design

  • event_information - содержит информацию о событии бронирования (для этого примера требуется только идентификатор)
  • event_machine_time - Здесь хранятся все ноутбуки, по три ряда на каждый ноутбук с уникальными временными интервалами, доступными на выбор
  • event_booking - Здесь хранится фактическое бронирование, которое затем ссылается на другую базу данных кандидатов, не включенную здесь

Затем я запускаю простой запрос, который объединяет все вместе и (я думал) идентифицирует зарезервированные события:

SELECT machine_laptop, machine_name, B.id AS m_id, C.id AS c_id, C.confirmed AS c_confirmed, C.live AS c_live, 
(C.id IS NOT NULL AND C.confirmed !=2 AND C.live !=0) AS booked
FROM event_information A
INNER JOIN event_machine_time B ON ( 1 =1 ) 
LEFT JOIN event_booking C on (B.id = C.machine_time_id and A.id = C.information_id )
WHERE A.id = :id
ORDER BY `B`.`id` DESC

booked проверяет, является ли confirmed не 2 -что означает, что бронирование былоОтменено / отклонено (0 - не подтверждено, 1 - подтверждено) и live проверяет удаление (0 - удалено, 1 - не удалено).

Однако, если лицо удаляется (live -0) или отменяет / отклоняет (confirmed - 2), затем в моем раскрывающемся списке выбора слотов переднего плана будет добавлен дополнительный слот, поскольку столбец booked по-прежнему равен 0, как показано ниже:

enter image description here

Это позволяет пользователю затем выбрать один из двух слотов одновременно, что означает двойное бронирование.

Теперь я знаю, что использование соединения - это не то, что нужноделать, и я предполагаю, что мне нужно запустить подзапрос, но я не эксперт по SQL, и я хотел бы получить некоторую помощь, чтобы найти примеры подобных «вторых запросов», из которых я могу извлечь уроки.

Также извиняюсь, если моя терминология неверна.

РЕДАКТИРОВАТЬ:

По запросу я включил вывод:

enter image description here

Второе редактирование и заключение:

В конце концов мне удалось создать решение вместеподпишите подзапрос, чтобы удалить отмененные / отклоненные заказы перед выводом, а затем используйте Group By, чтобы отобразить только один из каждого времени.Скорее всего, это не лучший способ, но он сработал для меня.

SELECT machine_laptop, machine_name, B.id AS m_id, C.id AS c_id, C.confirmed AS c_confirmed, C.live AS c_live, B.start_time AS b_start_time, (
            C.id IS NOT NULL 
            AND C.confirmed !=2
            AND C.live !=0
            ) AS booked
            FROM event_information A
            INNER JOIN event_machine_time B ON (1=1) 
            LEFT JOIN (SELECT * FROM event_booking WHERE confirmed <> '2' AND live <> '0') AS C ON ( B.id = C.machine_time_id AND A.id = C.information_id ) 
            WHERE A.id = :id
            GROUP BY m_id
            ORDER BY machine_name ASC, b_start_time ASC

Спасибо за ваш вклад.

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Если вы сделаете event_booking (B) отправной точкой для вашего запроса, вы увидите, что нет необходимости использовать вытягивание всех строк и столбцов из A и C. Впрочем, вы можете напрямую присоединиться к соответствующим строкам.Но так как я даже не могу правильно понять, к чему стремится ваш запрос, у меня сначала пара вопросов:

Хотя это может сработать, на самом деле это то, что не находится под вашим контролем и не определено вами.Некоторые более строгие режимы вежливо скажут вам указать, на какую таблицу псевдонимов вы ссылаетесь в вашем SELECT, так как этот

SELECT machine_laptop, machine_name  -- combined with
FROM event_information A 

на самом деле не имеет смысла, и единственная причина, почему он работает, это то, что вы 'снова используя оптимизацию MySQL.В дополнение к этому вы пытаетесь выполнять объединение таблиц в смешанном режиме (это означает, что вы используете методы JOIN и WHERE tA.colX = tB.colY. Это очень затрудняет отслеживание.

INNER JOIN event_machine_time B ON ( 1 =1 ) 

Хм? Какова именно цель этого? Насколько я могу сказать, это только приведет к тому, что он СОЕДИНЯЕТ обе полные таблицы, а затем отфильтрует результат, используя WHERE.

Кроме того, вы даже используетепервичные ключи? Ваше условие включает в себя C.id NOT NOT NULL , в то время как первичные ключи не могут даже содержать значения NULL (поскольку NULL является третьим логическим состоянием в стране SQL. Есть True, False и Null (означающее Undefined,который, очевидно, не может быть использован в первичном ключе, так как первичный ключ должен быть уникальным, а неопределенное значение может быть чем угодно или ничем - так что это нарушает требование уникальности). Поэтому я предполагаю, что вы фактически используете эту проверку NULL, потому что временнаятаблица во время JOIN, кажется, содержит их?

РЕДАКТИРОВАТЬ: Попытайтесь разделить это на две части, где вы сначала соединяете 2 таблицы, а затем присоединяетесь к третьейНе стесняйтесь результата.

Я предлагаю вам кратко остановиться на В чем разница между "INNER JOIN" и "OUTER JOIN"? - так как это довольно хороший пост и проясняет многие аспекты.

Для начала я бы выбрал что-то вроде:

SELECT
    <i.cols>,
    <b.cols>,
    <mt.cols>, 
    IF(b.confirmed !=2 AND b.live !=0, True, False) sa booked
FROM 
   event_booking b 
LEFT JOIN 
   event_information i ON b.information_id = i.id
LEFT JOIN 
   event_machine_time mt ON b.machine_time_id = mt.id
WHERE <conditions>

Позже я бы изменил LEFT JOIN на что-то более подходящее.Однако имейте в виду, что INNER JOIN полезен, только если вы на 100% уверены, что строки, возвращаемые из столбцов объединенной таблицы, уникальны.

Может ли даже быть отношение 1: n, n: 1 между i и bтаблицы?Я бы предположил, что не может быть несколько бронирований для одной и той же информации о событии (n: 1), и при этом не было бы так, чтобы информация о событии была одинаковой для нескольких событий?(1: N) * * тысяча двадцать-шесть

0 голосов
/ 23 октября 2018

Попробуйте ниже:

SELECT machine_laptop, machine_name, B.id AS m_id, C.id AS c_id, C.confirmed 
AS c_confirmed, C.live AS c_live, 
(C.id IS NOT NULL AND C.confirmed !=2 AND C.live !=0) AS booked
FROM event_information A
LEFT JOIN event_booking C ON A.id = C.information_id
RIGHT JOIN event_machine_time B ON B.id = C.machine_time_id
WHERE A.id = :id
ORDER BY `B`.`id` DESC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...