2009-06-12 17 views
5

Tengo dos mesas, una para aperturas y la otra para reservas. Una entrada en la tabla de reservas siempre se refiere a una apertura y puede haber múltiples reservas para cada apertura. Me gustaría extraer todas las aberturas que tienen reservas diferentes de bookingType 'C'.Consulta SQL: ¿Dónde me estoy equivocando?

E.g.

  1. si una abertura tiene 3 reservas de tipo A, B y C, no debería aparecer en el resultado

  2. si una abertura tiene sólo reservas de tipo A y B, se debe mostrar en el resultado

lo siguiente es lo que he intentado pero no es correcta, ya que falla para el ejemplo 1:

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

Ésta es la consulta completa refiriendo a intervalos de tiempo:

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')) 

lo que solía llamar bookingType era en realidad un intervalo de tiempo definido a través de las dos columnas arrivalDate y departureDate: en el ejemplo anterior que necesito toda la aberturas que NO tienen una reserva entre 20th June 2009 y 27th June 2009.

+0

¿Tiene la estructura de su mesa? Esto también suena como tarea. –

+0

abertura TABLA Identificación del INT NOT NULL Descripción VARCHAR (60) PRIMARY KEY (id) reserva TABLA Identificación del INT NOT NULL, openingId INT NOT NULL, arrivalDate DATETIME NOT NULL, DepartureDate DATETIME NOT NULL, PRIMARIA KEY (id) Estoy tratando de extraer todas las aberturas disponibles para un determinado intervalo de fechas (por ejemplo, del 20-06-2009 al 27-06-2009) –

+0

¿dónde está el bookingType en el ejemplo anterior? – akf

Respuesta

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

con el cambio de fecha:

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

En teoría, esto era lo que intentaba evitar ... una subconsulta suena un poco pesada, pero funciona –

+0

Considere la solución de sintaxis de unión izquierda de aaron también. Una combinación a la izquierda suele ser más rápida que una no en subconsulta. – HLGEM

+0

Una buena base de datos SQL normalmente optimizará una subconsulta en una combinación a la izquierda para que tenga el mismo rendimiento. Escriba la declaración con una subconsulta: es más fácil codificar y comprender. –

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 La subconsulta no hace nada aquí? – Andomar

+0

En realidad ... hace una combinación externa izquierda. Y la consulta principal filtra el resultado de la combinación externa izquierda ... –

+0

¿Pero una combinación externa izquierda y dónde se puede hacer sin una subconsulta? – Andomar

2

Aquí está una versión fácil sin juntas, que ni siquiera necesita la tabla Aberturas:

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

@Frankie - n necesidad de una cláusula NOT IN. Puede utilizar una izquierda anti-Semi Ingreso también - como esto:

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 

y esto:

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 
Cuestiones relacionadas