2015-03-31 2 views
0

Я пытаюсь создать представление в Oracle, чтобы показать все номера в отеле, которые не забронированы.Ошибка Oracle union

Если они забронированы, там будет запись в RoomBasket. Поэтому я стараюсь выбрать все номера не в RoomBasket между датами проверки и проверки (RoomBasket.datein, RoomBasket.dateout)

Но запрос продолжал возвращать 0 результатов, когда я использовал внутренние соединения и внешние (влево/вправо) соединения , Я думаю, это потому, что он не присоединился к таблице дат, поэтому он будет иметь 0 результатов. Итак, теперь я пытаюсь сделать «Union to the Room» таблицу, в которой есть запись обо всех комнатах, так как я думаю, что выберете все номера, а затем отмените те, которые были забронированы?

Я не могу получить синтаксис правильно, и я играл с нагрузками форм этого запроса:

CREATE VIEW availability AS 
    (SELECT * FROM RoomBasket rb 
     WHERE TO_DATE(SYSDATE, 'yyyymmdd') 
     NOT BETWEEN TO_DATE(rb.datein, 'yyyymmdd') AND TO_DATE(rb.dateout, 'yyyymmdd') 
     UNION (SELECT r.id room, rt.type type, rt.price price FROM Room r, RoomType rt) 
    ); 

Но если это работает я получаю 0 результат, и если он не работает, я получаю ошибки синтаксиса , На данный момент ошибка:

блок запроса имеет неправильное число столбцов результата

+0

Не используйте 'SELECT *' в первом запросе, фактически перечислите нужные столбцы. «UNION» требует одинаковое количество столбцов во всех запросах. – Taryn

+0

@bluefeet Хорошо получилось, что он работает спасибо! – Paul

ответ

3

У вас нет предиката на ваш джойн Room к RoomType, так что вы получите перекрестное соединение. Это вряд ли будет тем, что вы хотите.

Кроме того, ваш union выглядит так, будто он пытается добавить несвязанные данные в данные о комнате. Ваше описание проблемы предполагает, что вы хотите использовать данные RoomBasket для фильтра вместо других данных - для этого требуется соединение или подзапрос.

Что-то больше вдоль этих линий будет делать то, что вы хотите:

CREATE VIEW availability AS (
    SELECT r.id room, rt.type type, rt.price price 
    FROM 
    Room r 
    INNER JOIN RoomType rt 
     ON rt.id = r.type 
    LEFT JOIN RoomBasket rb 
     ON rb.room = r.id 
     AND TO_DATE(SYSDATE, 'yyyymmdd') BETWEEN TO_DATE(rb.datein, 'yyyymmdd') 
      AND TO_DATE(rb.dateout, 'yyyymmdd') 
    WHERE rb.room IS NULL 
); 

WHERE предикат имеет эффект выбора этих строк левой таблицы (Room JOIN RoomType), которые не соответствовали по любой строке правой таблицы (RoomBasket).

3

Ваш первый запрос возвращает разное количество столбцов, чем ваш второй запрос, таким образом, они не могут быть unioned. Указать столбцы для первого запроса явно, а не использовать SELECT *.

0

Я получил это работает правильно, как это:

CREATE VIEW availability AS 
      (SELECT 
       r.id room, 
       rt.type type, 
       rt.price price 
       FROM Room r 
       INNER JOIN RoomType rt ON r.type = rt.id 
       INNER JOIN RoomBasket rb ON r.id = rb.room 
       WHERE TO_DATE(SYSDATE, 'DD-Mon-YYYY') 
        NOT BETWEEN TO_DATE(rb.datein, 'DD-Mon-YYYY') 
          AND TO_DATE(rb.dateout, 'DD-Mon-YYYY') 
      ) 
    ; 
+0

Похоже, что это означает, что вы возвращаете дубликаты комнат с несколькими соответствующими строками 'RoomBasket' ​​за пределами диапазона дат, который вы используете. Однако для меня достаточно информации, чтобы обновить свой ответ с помощью правильных имен столбцов. –

+0

@JohnBollinger Да, тот дал неверный результат, но я получил его, работая уже вот так. Отредактировал ответ. – Paul

+0

Нет, это еще хуже. Мало того, что он все еще может производить обманы, он также будет * пропустить * комнаты, которые не имеют соответствующей строки 'RoomBasket'. Возможно, ваши данные «RoomBasket» таковы, что это приводит к ожидаемому результату, но форма запроса не гарантирует, что он будет продолжать это делать. –

Смежные вопросы