如何在MySQL中相交两个查询

时间:2019-05-30 18:48:59

标签: mysql intersection

我在数据库中有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不会将元组识别为相同的元组。

任何帮助将不胜感激。

2 个答案:

答案 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中的查询已经有了代码,因此您甚至不需要执行外部查询。但是我补充说,以防您需要机场表中的信息,而您又不需要在问题中指定该信息。