2009-06-12 37 views
5

Tôi có hai bàn, một cái để mở và cái kia để đặt. Một mục trong bảng đặt phòng luôn đề cập đến việc mở và có thể có nhiều đặt chỗ cho mỗi lần mở. Tôi muốn trích xuất tất cả các lần mở có đặt phòng khác với bookingType 'C'.Truy vấn SQL - Tôi đang đi sai ở đâu?

Ví dụ:

  1. nếu một khe hở có 3 việc đặt các loại A, B và C, nó nên không hiển thị trong kết quả

  2. nếu một khe hở chỉ có đặt loại A và B, nó sẽ hiển thị lên trong kết quả

sau đây là những gì tôi đã cố gắng nhưng nó không phải là chính xác vì nó không cho ví dụ 1:

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

Dưới đây là các truy vấn hoàn chỉnh đề cập đến khoảng thời gian:

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

Những gì tôi sử dụng để gọi bookingType thực sự là một khoảng thời gian được xác định thông qua hai cột arrivalDatedepartureDate: trong ví dụ trên, chúng tôi cần tất cả các các lỗ trống KHÔNG đặt trước giữa 20th June 200927th June 2009.

+0

Bạn có cấu trúc bảng của bạn? Điều này cũng giống như bài tập về nhà. –

+0

TABLE mở id INT NOT NULL mô tả VARCHAR (60) PRIMARY KEY (id) TABLE đặt phòng id INT NOT NULL, openingId INT NOT NULL, arrivalDate DATETIME NOT NULL, departureDate DATETIME NOT NULL, TIỂU KEY (id) Tôi đang cố gắng trích xuất tất cả các lần mở có sẵn trong một khoảng thời gian nhất định (ví dụ: từ ngày 20-06-2009 đến ngày 27-06-2009) –

+0

trong đó loại đặt chỗ trong ví dụ trên là gì? – akf

Trả lời

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

với sự thay đổi ngày:

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

Về lý thuyết đây là những gì tôi đã cố gắng để tránh ... một subquery âm thanh một chút nặng, nhưng nó hoạt động –

+0

Hãy xem xét các giải pháp cú pháp tham gia bên trái từ aaron là tốt. Liên kết bên trái thường nhanh hơn so với truy vấn con không phải trong truy vấn phụ. – HLGEM

+0

Một cơ sở dữ liệu SQL tốt thường sẽ tối ưu hóa truy vấn phụ vào một phép nối trái để nó có cùng hiệu năng. Viết câu lệnh với truy vấn phụ - nó dễ dàng hơn để viết mã và hiểu. –

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 Truy vấn con không làm gì ở đây? – Andomar

+0

Thực ra ... nó tham gia bên ngoài bên trái. Và truy vấn chính lọc kết quả của phép nối ngoài bên trái ... –

+0

Nhưng một phép nối ngoài bên trái và nơi có thể được thực hiện mà không có truy vấn phụ? – Andomar

2

Dưới đây là một phiên bản dễ dàng mà không cần tham gia, bạn thậm chí không cần bảng khởi đầu:

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

@Frankie - Không cần cho một mệnh đề NOT IN. Bạn có thể sử dụng một trái Anti-Semi Tham gia cũng - như thế này:

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 

và điều này:

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 
Các vấn đề liên quan