相同的查询给出不同的结果

Same queries giving different results

因此,对于学校的作业,我们必须从数据库中提取计数。问题如下,

--19) 包含 'Europe' 的时区名称中有多少个机场被用作源机场 (source_airport_id),用于飞机尾流为 'M' 的航线] 或 'L'

这是我想出的代码,

SELECT count(DISTINCT airports.id) FROM airports WHERE timezone_name LIKE '%Europe%' AND id IN
(SELECT source_airport_id FROM routes WHERE id IN 
(SELECT id FROM route_aircrafts WHERE aircraft_id IN 
(SELECT id FROM aircrafts WHERE wake_size IN ('M', 'L'))));

它返回了 544,而教授的答案返回了 566。

SELECT count (DISTINCT airports.id)
FROM airports, routes, route_aircrafts, aircrafts

WHERE airports.id = routes.source_airport_id
AND routes.id = route_aircrafts.route_id
AND aircrafts.id = route_aircrafts.aircraft_id

AND airports.timezone_name LIKE'%Europe%'
AND aircrafts.wake_size IN ('M', 'L'); --566

对我来说,这两个应该做同样的事情,我不明白为什么答案不同。

要在您的查询中获得相同的答案,您需要:

SELECT count(DISTINCT airports.id) FROM airports WHERE timezone_name LIKE '%Europe%' AND id IN
(SELECT source_airport_id FROM routes WHERE id IN 
(SELECT route_id FROM route_aircrafts WHERE aircraft_id IN 
(SELECT id FROM aircrafts WHERE wake_size IN ('M', 'L'))));

您使用了主 ID 字段而不是外键 route_id。您得到的结果大致相似,因为值中肯定有明显的重叠。

我会按照以下方式去做:

SELECT COUNT(DISTINCT airports.id)
FROM airports 
INNER JOIN routes ON airports.id = routes.source_airport_id
INNER JOIN route_aircrafts ON routes.id = route_aircrafts.route_id
INNER JOIN aircrafts ON route_aircrafts.aircraft_id = aircrafts.id
    AND aircrafts.wake_size IN ('M', 'L')
WHERE airports.timezone_name LIKE '%Europe%'

解释:

SELECT COUNT(DISTINCT airports.id)

您不想多次计算重复的 airports.id

FROM airports 

这是您计数的主要 table。所有其他 table 都是从这个构建的。

INNER JOIN routes ON airports.id = routes.source_airport_id

INNER JOIN 将只包括在两个 table 中匹配的行。匹配 airports.idroutes.source_airport_id.

INNER JOIN route_aircrafts ON routes.id = route_aircrafts.route_id

INNER JOIN 将只包括在两个 table 中匹配的行。匹配 routes.idroute_aircrafts.route_id.

INNER JOIN aircrafts ON route_aircrafts.aircraft_id = aircrafts.id
AND aircrafts.wake_size IN ('M', 'L')

与上面的 INNER JOINs 相同。我们为 wakes 添加了一个额外的过滤器。对于 INNER JOIN,也可以在 WHERE 子句中执行此筛选器而不更改结果。将过滤器放在 JOIN 中可以使意图保持一致(并且优化器可能会以这种方式进行过滤)。对于 OUTER JOIN,在 JOIN 中过滤与在 WHERE 中过滤可能 return 不同的结果(取决于您的数据)。

WHERE airports.timezone_name LIKE '%Europe%'

现在我们通过 airports 的基数 table 中的 timezone_name 过滤整个结果集。

使用 SQL 时,请务必考虑 SETS 中的数据。这将帮助您编写性能更高、程序化更少的查询。