我在数据库中有3个表,如下所示:
airlines
+----+-----------------+-------+---------+
| Id | Name | Abbr | Country |
+----+-----------------+-------+---------+
| 1 | United Airlines | UAL | USA |
| 2 | US Airways | USAir | USA |
|... | ... | ... | ... |
+----+-----------------+-------+---------+
airports
+--------------+------+-------------+---------------+-------+
| City | Code | Name | Country | CAbbr |
+--------------+------+-------------+---------------+-------+
| Apalachicola | AAF | Municipal | United States | US |
| Abilene | ABI | US Airways | United States | US |
| ... | ... | ... | ... | ... |
+--------------+------+-------------+---------------+-------+
flights
+---------+----------+--------+-------------+
| Airline | FlightNo | Source | Destination |
+---------+----------+--------+-------------+
| 1 | 28 | APG | ASY |
| 1 | 44 | CVO | ACV |
| ... | ... | ... | ... |
+---------+----------+--------+-------------+
我正在尝试报告Frontier和JetBlue服务的所有机场对。每个机场对必须准确地报告一次(如果报告了X,Y对,那么Y,X对就是多余的,不应报告)。
我相信我知道如何分别获得Frontier航班和JetBlue航班:
SELECT ap1.Code, ap2.Code
FROM flights f, airports ap1, airports ap2, airlines al
WHERE ap1.Code = f.Source
AND ap2.Code = f.Destination
AND f.Airline = al.Id
AND al.Abbr = 'Frontier'
ORDER BY ap1.Code ASC;
SELECT ap1.Code, ap2.Code
FROM flights f, airports ap1, airports ap2, airlines al
WHERE ap1.Code = f.Source
AND ap2.Code = f.Destination
AND f.Airline = al.Id
AND al.Abbr = 'JetBlue'
ORDER BY ap1.Code ASC;
但是我不明白如何获得它们之间的交点。我已经尝试了LEFT JOIN和WHERE EXISTS,但是我做错了,因为我得到的看起来更像是一个Union,而不是一个Intersection。这是我最近的尝试(肯定是错误的)。
SELECT ap1.Code, ap2.Code AS code
FROM airports ap1, airports ap2
WHERE
EXISTS (SELECT ap1.Code, ap2.Code
FROM flights f, airports ap1, airports ap2, airlines al
WHERE ap1.Code = f.Source
AND ap2.Code = f.Destination
AND f.Airline = al.Id
AND al.Abbr = 'Frontier') AND
EXISTS (SELECT ap1.Code, ap2.Code
FROM flights f, airports ap1, airports ap2, airlines al
WHERE ap1.Code = f.Source
AND ap2.Code = f.Destination
AND f.Airline = al.Id
AND al.Abbr = 'JetBlue')
ORDER BY ap1.Code ASC;
一旦找到交集,我就不太确定如何区分X,Y对和Y,X对,因为DISTINCT不会将元组识别为相同的元组。
任何帮助将不胜感激。
答案 0 :(得分:0)
如果同时需要两者,则可以尝试使用IN航空公司
SELECT ap1.Code, ap2.Code
FROM flights f
INNER JOIN airports ap1 ON ap1.Code = f.Source
INNER JOIN airports ap2 ON ap2.Code = f.Destination
INNER JOIN airlines al ON f.Airline = al.Id
WHERE al.Abbr IN ( 'Frontier', 'JetBlue')
ORDER BY ap1.Code ASC;
您应该避免基于位置而使用old(1992)隐式联接sintax并使用显式联接sintax
答案 1 :(得分:0)
SELECT apPairs.*, ap1.stuff, ap2.stuff
FROM (
SELECT LEAST(f.Source, f.Destination) AS ap1Code
, GREATEST(f.Source, f.Destination) AS ap2Code
FROM airlines AS al
INNER JOIN flights AS f ON al.Id = f.Airline
WHERE al.Abbr IN ('Frontier', 'JetBlue')
GROUP BY ap1Code, ap2Code
HAVING COUNT(DISTINCT al.Abbr) = 2 -- Served by both airlines
) AS apPairs
INNER JOIN airports AS ap1 ON apPairs.ap1Code = ap1.Code
INNER JOIN airports AS ap2 ON apPairs.ap1Code = ap2.Code
;
我使用LEAST和GREATEST合并了所有(X,Y)和(Y,X)冗余;这些功能是特定于MySQL的,因此在其他RDBMS中,您可能需要创建自己的版本。 注意:根据数据的使用方式,您可能需要仔细检查以下假设:x-> y和y-> x对确实是多余的;航空公司可能(至少在现实中)拥有X-> Y-> Z-> X航线,但没有直接的Y-> X。
HAVING子句中的COUNT(DISTINCT)确保仅对每个航空公司的缩写计数一次,因此100个航班不会使数字膨胀。它在查询中的使用可确保您获得的是两家航空公司提供的机场,而不是 两家航空公司。
由于apPairs中的查询已经有了代码,因此您甚至不需要执行外部查询。但是我补充说,以防您需要机场表中的信息,而您又不需要在问题中指定该信息。