2009-06-12 7 views
5

J'ai deux tables, une pour les ouvertures et l'autre pour les réservations. Une entrée dans la table des réservations se réfère toujours à une ouverture et il peut y avoir plusieurs réservations pour chaque ouverture. Je voudrais extraire toutes les ouvertures qui ont des réservations différentes de bookingType 'C'.Requête SQL - Où vais-je me tromper?

E.g.

  1. si une ouverture a 3 réservations de type A, B et C, il ne devrait pas apparaître dans le résultat

  2. si une ouverture n'a que les réservations de type A et B, il doit montrer dans le résultat

Voici ce que je l'ai essayé, mais il est inexact car il échoue pour l'exemple 1:

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

Voici la requête complète se référant à des intervalles de temps:

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

Ce que je l'habitude d'appeler bookingType était en fait un intervalle de temps défini par les deux colonnes arrivalDate et departureDate: dans l'exemple ci-dessus je besoin de tous les ouvertures qui n'ont pas de réservation entre le 20th June 2009 et le 27th June 2009.

+0

Avez-vous la structure de votre table? Cela ressemble aussi à des devoirs. –

+0

TABLE ouverture id INT NOT NULL Description VARCHAR (60) PRIMARY KEY (id) TABLE réservation id INT NOT NULL, openingId INT NOT NULL, arrivalDate DATETIME NOT NULL, departureDate DATETIME NOT NULL, PRIMAIRE KEY (id) J'essaie d'extraire toutes les ouvertures qui sont disponibles pour un certain intervalle de dates (par exemple du 20-06-2009 au 27-06-2009) –

+0

où est le bookingType dans l'exemple ci-dessus? – akf

Répondre

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

avec le changement de date:

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 théorie, c'était ce que j'essayais d'éviter ... une sous-requête semble un peu lourde, mais cela fonctionne –

+0

Considérons également la solution de syntaxe de jointure gauche d'Aaron. Une jointure à gauche est souvent plus rapide qu'une sous-requête. – HLGEM

+0

Une bonne base de données SQL optimisera généralement une sous-requête dans une jointure à gauche afin qu'elle ait les mêmes performances. Ecrire la déclaration avec une sous-requête - il est plus facile de coder et de comprendre. –

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 sous-requête ne fait rien ici? – Andomar

+0

En fait ... il fait une jointure externe gauche. Et la requête principale filtre le résultat de la jointure externe gauche ... –

+0

Mais une jointure externe gauche et où peut-on faire sans sous-requête? – Andomar

2

Voici une version facile sans jointures, vous ne même pas besoin de la table Ouvertures:

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

@Frankie - Non besoin d'une clause NOT IN. Vous pouvez utiliser une gauche anti-Semi s'y joindre - comme ceci:

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 

et ceci:

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