2009-06-12 7 views
5

У меня есть два стола, один для открытий, а другой для заказов. Запись в таблице бронирования всегда относится к открытию, и для каждого открытия может быть несколько заказов. Я хотел бы извлечь все отверстия, у которых есть заказы, отличные от bookingType 'C'.SQL Query - Где я ошибаюсь?

E.g.

  1. , если отверстие имеет 3 заказы типа А, В и С, он не должен отображаться в результате

  2. , если отверстие имеет только заказы типа А и В, он должен показать вверх в результате

Ниже то, что я пытался, но это не правильно, как он не для примера 1:

select op.id, bo.id 
    from opening op 
    left join booking bo on bo.openingId = op.id 
    where bo.bookingType != 'C'; 

Вот полный запрос со ссылкой на временные интервалы:

select op.id, bo.id 
    from opening op 
    left join booking bo on bo.openingId = op.id 
    where ((bo.arrivalDate < '2009/06/20' AND bo.departureDate <= '2009/06/20') OR 
     (bo.arrivalDate >= '2009/06/27' AND bo.departureDate > '2009/06/27')) 

То, что я называл bookingType был фактически временной интервал определяется через две колонки arrivalDate и departureDate: в приведенном выше примере, мне нужно все которые НЕ ДОПУСКАЮТСЯ между 20th June 2009 и 27th June 2009.

+0

У вас есть структура таблицы? Это также звучит как домашнее задание. –

+0

открытие Таблица ID INT NOT NULL Описание УАКСНАК (60) первичный ключ (идентификатор) Таблица бронирование ID INT NOT NULL, openingId INT NOT NULL, ArrivalDate DATETIME NOT NULL, departureDate DATETIME NOT NULL, ПЕРВИЧНЫЙ KEY (id) Я пытаюсь извлечь все отверстия, доступные для определенного интервала дат (например, с 20-06-2009 по 27-06-2009) – 2009-06-12 12:30:43

+0

где находится тип бронирования в приведенном выше примере? – akf

ответ

7
SELECT op.id 
FROM opening op 
WHERE op.id NOT IN 
    (SELECT b.openingid 
     FROM booking b 
     WHERE b.bookingtype='C') 

с изменением даты:

SELECT op.id 
FROM opening op 
WHERE op.id NOT IN 
    (SELECT b.openingid 
     FROM booking b 
     WHERE (b.arrivalDate BETWEEN '2009/06/20' AND '2009/06/27') 
      OR 
      (b.departureDate BETWEEN '2009/06/20' and '2009/06/27') 
    ) 
+0

В теории это то, чего я пытался избежать ... подзапрос звучит немного тяжело, но он работает – 2009-06-12 13:07:26

+0

Рассмотрите левое синтаксическое решение соединения от aaron. Левое соединение часто бывает быстрее, чем не в подзапросе. – HLGEM

+0

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

0
select opid, boid from 
    (select op.id opid, bo.id boid, bo.bookingType bookingType 
     from 
     openings op left outer join bookings bo on op.id = bo.id 
    ) 
where bookingType <> 'C' 
+0

-1 Подзапрос здесь ничего не делает? – Andomar

+0

На самом деле ... он делает левое внешнее соединение. И главный запрос фильтрует результат левого внешнего соединения ... –

+0

Но левое внешнее соединение и где можно сделать без подзапроса? – Andomar

2

Вот простой вариант без соединения, вам даже не нужны отверстия таблицы:

select openingId, id 
from booking 
where openingId not in (
    select openingId 
    from booking 
    where bookingType = 'C' 
) 
1

@Frankie - Нет необходимо для предложения NOT IN. Вы можете использовать левую Анти-Semi Регистрацию, а также - как это:

SELECT op.id 
FROM opening op 
LEFT OUTER JOIN booking b ON op.id = b.openingid AND b.bookingtype = 'C' 
WHERE b.OpeningID IS NULL 

и это:

SELECT op.id 
FROM opening op 
LEFT OUTER JOIN booking b ON op.id = b.OpeningID 
AND b.ArrivalDate BETWEEN '2009/06/20' AND '2009/06/27' 
AND b.DepartureDate BETWEEN '2009/06/20' AND '2009/06/27' 
WHERE b.OpeningID IS NULL 
Смежные вопросы