2017-10-07 84 views
0

我有如下表:卡在「在條款」

create table passenger (passenger_ID varchar (10) , passenger_name varchar (30) , passenger_city varchar (30) , primary key (passenger_ID)) ; 
    create table flight (flight_number varchar (10) , departure_airport varchar (10), arrival_airport varchar (10) , primary key (flight_number)); 

    create table seat ( 
    flight_number varchar (10), 
    seat_number varchar (10), 
    primary key(flight_number, seat_number), 
    foreign key(flight_number) references flight); 

    create table reservation(
  passenger_ID varchar (10) 
  flight_number varchar (10) , seat_number varchar (10) , 
    day date ,
  fare numeric(8,2), 
    primary key (flight_number, seat_number,day), 
    foreign key (flight_number, seat_number) references seat) , 
    foreign key (passenger_ID) references passenger ; 

我被困在了這個問題: 查找保留一個航班每位乘客的ID(或航班)從「ALB」出發,從未預訂到達'ALB'的航班。對於此查詢,請使用in子句或not in子句。

我寫了這麼多查詢:

select a.passenger_id from 
reservation a 
where a.flight_number in (select b.flight_number from flight b where 
             b.departure_airport = 'ALB' 
            and b.arrival_airport <> 'ALB'); 

但這種查詢是不正確的。子查詢返回與過濾條件相匹配的所有航班號。但是主要的select查詢會返回子查詢返回的flight_number的所有乘客id,即使該乘客的arrival_airport是ALB。

我的預約表:

passenger_id flight_number seat_number day fare 
2 A2 201 10/1/17 1083 
1 A3 301 10/1/17 1173.25 
1 A4 402 10/1/17 846.81 
2 A5 501 10/1/17 752.72 
1 A5 502 10/1/17 485 
4 A5 506 10/1/17 970 
2 A6 601 10/1/17 388 
1 A7 703 10/1/17 921.5 
3 A7 704 10/1/17 921.5 
2 A8 804 10/1/17 970 
4 A8 805 10/1/17 970 

我的飛行表:

flight_number departure_airport arrival_airport 
A1 Ktm Pkr 
A2 Ktm NY 
A3 Ktm Ind 
A4 Ktm Chn 
A5 ALB KTM 
A6 ALB PKR 
A7 KTM ALB 
A8 PKR ALB 

回答

2

想:兩個條件。所以從你的思路來看:

select r.passenger_id 
from reservation r 
where r.flight_number in (select f.flight_number 
          from flight f 
          where f.departure_airport = 'ALB' 
         ) and 
     r.flight_number not in (select f.flight_number 
           from flight f 
           where f.arrival_airport = 'ALB' 
          ); 

但是,那不行。任何到達ALB的航班都將從其他機場出發。所以,這只是選擇所有預訂ALB航班的乘客。此邏輯在航班級別,而不是乘客級別。

嗯。您實際上需要的信息是所有航班客戶「一次」。這表明聚合:

select r.passenger_id 
from reservation r join 
    flight f 
    on r.flight_number = f.flight_number 
group by r.passenger_id 
having sum(case when f.departure_airport = 'ALB' then 1 else 0 end) > 0 and -- reserved a flight from ALB 
     sum(case when f.arrival_airport = 'ALB' then 1 else 0 end) = 0;  -- never reserved a flight to ALB 
+0

對不起,它沒有工作。請看我的桌子。只有A5和A6航班從ALB出發。所以,乘客ID 1,2和4是符合條件的。但passenger_id 4已預約到達ALB,因此應予以忽略。所以我應該只得到1和2乘客ID –

+0

@SujanShrestha。 。 。你使用了「GROUP BY」查詢嗎?也許你應該設置一個SQL小提琴或Rextester。 –

+0

http://sqlfiddle.com/#!17/deeeb/1 –

1

只是爲了以稍微不同的方式證明@ GordonLinoff的答案的正確性,讓我們稍微區別看待它。 :-)(See this SQLFiddle)。 (請注意,我填充了PASSENGER表,我們稍後會使用它。:-)。首先,讓我們抓住所有誰已預留至少一個航班從ALB離開的乘客:

-- Find passengers who have reserved at least one flight departing from ALB 

SELECT DISTINCT r.PASSENGER_ID 
    FROM RESERVATION r 
    INNER JOIN FLIGHT f 
    ON f.FLIGHT_NUMBER = r.FLIGHT_NUMBER 
    WHERE f.DEPARTURE_AIRPORT = 'ALB'; 

這將返回PASSENGER_ID的1,2,4

接下來,讓我們找到所有誰在保留乘客至少一個飛行到達ALB:

-- Find passengers who have reserved at least one flight arriving at ALB 

SELECT DISTINCT r.PASSENGER_ID 
    FROM RESERVATION r 
    INNER JOIN FLIGHT f 
    ON f.FLIGHT_NUMBER = r.FLIGHT_NUMBER 
    WHERE f.ARRIVAL_AIRPORT = 'ALB'; 

這返回PASSENGER_ID的1,2,3和4。

上述結果的瑣碎審查表明顯然,沒有任何乘客預訂了ALB航班,並且沒有預訂到達ALB的航班。但是因爲我們只想讓查詢向我們展示我們想要什麼,而不必去思考(畢竟,這是計算機應該做的事情:-)我們將把上述查詢放在一起:

-- Now put them together 

SELECT p.PASSENGER_ID 
    FROM PASSENGER p 
    INNER JOIN (SELECT DISTINCT r.PASSENGER_ID 
       FROM RESERVATION r 
       INNER JOIN FLIGHT f 
        ON f.FLIGHT_NUMBER = r.FLIGHT_NUMBER 
       WHERE f.DEPARTURE_AIRPORT = 'ALB') d 
    ON d.PASSENGER_ID = p.PASSENGER_ID 
    LEFT OUTER JOIN (SELECT DISTINCT r.PASSENGER_ID 
        FROM RESERVATION r 
        INNER JOIN FLIGHT f 
         ON f.FLIGHT_NUMBER = r.FLIGHT_NUMBER 
        WHERE f.ARRIVAL_AIRPORT = 'ALB') a 
    ON a.PASSENGER_ID = p.PASSENGER_ID 
    WHERE a.PASSENGER_ID IS NULL; 

如預期的那樣,此查詢不返回任何結果。

但...我們真的想確保我們的查詢真的有效。 Soooo ...讓我們添加幾行到幾個表。首先,我們將添加一個新的乘客:

insert into passenger (passenger_ID, passenger_name, passenger_city) 
    values ('5', 'Bugs Bunny', 'ABC'); 

,我們還會增加對兔子先生,一個在那裏,他離開ALB航班:

INSERT INTO RESERVATION (PASSENGER_ID, FLIGHT_NUMBER, SEAT_NUMBER, DAY, FARE) 
    VALUES ('5', 'A6', '123', TO_DATE('2017-10-01','YYYY-MM-DD'), 400); 

所以現在我們有乘員5,先生B. Bunny,離開ALB--但他從未飛入ALB。 (我認爲那是因爲他應該在阿爾伯克基左轉彎:-)。所以我們的查詢應該返回乘客5,並且if you go look at this SQLFiddle你會看到發生的情況。

Ehhh - 祝你好運,doc。

1

集中在乘客的替代航班,使用IN()NOT IN()

SELECT DISTINCT 
     r.passenger_id 
FROM reservation r 
WHERE r.passenger_id IN (
     SELECT 
      r.passenger_id 
     FROM RESERVATION r 
     INNER JOIN FLIGHT f ON f.flight_number = r.flight_number 
     WHERE f.DEPARTURE_AIRPORT = 'ALB' 
    ) 
AND r.passenger_id NOT IN (
     SELECT 
      r.passenger_id 
     FROM RESERVATION r 
     INNER JOIN FLIGHT f ON f.flight_number = r.flight_number 
     WHERE f.ARRIVAL_AIRPORT = 'ALB' 
    ) 
; 

但是鮑勃賈維斯分析也表明,在您的樣本數據中沒有行符合分配條件。

+0

:這個問題也可以使用SET OPERATIONS來解決嗎? –

+0

不確定你的意思。我個人很少使用IN(),除非它是一個固定的值列表。您可以輕鬆地將上述查詢轉換爲使用EXISTS&NOT EXISTS,並且Gordon Linoff顯示了HAVING的用法。 –

+0

哦,Bob Jarvis也展示瞭如何使用聯合派生表。所以你有很多可以從恕我直言選擇 –