SQL 相关子查询
SQL correlated subqueries
我已经在 Codecademy 上做这个练习好几天了,仍然无法理解背后的逻辑it.Below是练习和代码:
通过为航班提供基于时间的序列号(由承运人提供)来订购航班会很有趣。
例如,假设 flight_id 随着每个额外航班的增加而增加,我们可以使用以下查询按承运人、航班 ID 和序列号查看航班:
SELECT carrier, id,
(SELECT COUNT(*)
FROM flights f
WHERE f.id < flights.id
AND f.carrier=flights.carrier) + 1 AS flight_sequence_number
FROM flights;
我能理解f
是tableflights
的虚拟形式,但是f.id < flights.id
有什么作用呢?这是否意味着 SQL 将 f
中的每一行与 flights
中的每一行进行比较,例如
比较 MQ 17107 与 MQ 7869,
比较 MQ 17107 与 MQ 2205,
比较 MQ 17107 与 MQ 14979
……
将 MQ 7869 与 MQ 2205 进行比较,
比较 MQ 7869 与 MQ 14979
……
此外,这个 COUNT(*)
到底算什么?为什么 +1
?
这是结果图片:query result
如有任何帮助,我们将不胜感激。谢谢。
查询从 table 个航班中选择记录。对于每条记录,它选择承运人、id 和 flight_sequence_number.
因此,对于航班中的每条记录,都会执行子查询。它再次读取 table 个航班,但只记录具有相同承运人且航班 ID 小于主记录之一的记录。要说主查询记录和子查询记录,需要一两个table别名,否则两个记录都叫flight.id中的flight,就不清楚是哪一个了你正在谈论的一个。所以内部查询中的 table 得到别名 f。现在你可以比较 f.id < flights.id 和 f.carrier = flights.carrier.
COUNT(*) 因此计算低于其承运人的主记录航班 ID 的所有记录,从而对承运人的行进行编号。对于最小的 ID,您找不到更小的 ID,因此计数为 0,您添加一个,从而得到行号 1。对于第二小的 ID,您找到一个 ID 较小的记录,因此您得到计数 1,加 1 并得到行号 2等等。
如果您添加 order by 子句 ORDER BY carrier, id
,结果会更好看,因此您会按照使用的顺序显示结果。
如前所述,一些现代 DBMS 提供了分析功能,例如 ROW_NUMBER
并且查询变得更加简单:
select
carrier,
id,
row_number() over (partition by carrier order by id) as flight_sequence_number
from flights
order by carrier, id;
您有一个带有 flight_id 的航班列表,它告诉您所有航班相对于彼此的顺序。您正在查看的查询试图做的是获取仅与同一承运人的航班相关的每个航班的顺序。例如,如果我问你第 50 次航班是什么,那会很容易,因为你可以用 flight_id = 50 查找航班。但是如果我问你第 50 次美国航空公司的航班是什么,你不会我对 table 没有任何聚合或分区使用的情况有任何想法。
让我们看一个简单的 select 查询。如果你 select 给定类型 A 的所有运营商,你会得到这样的东西:
SELECT flight_id, carrier
FROM flights
WHERE carrier = A
flight_id, carrier
------------------
4, A
9, A
10, A
18, A
20, A
25, A
26, A
然而,当我们只查看承运人 A 时,flight_id
不再是序列号。ID 为 4 的航班不是我们结果的第 4 个航班(即航班 18)。然后我们可以聚合数据,这样我们就有了每个航班相对于同一承运人航班的顺序。所以我们要做的就是在每一行之前统计相同类型的航班数量,得到它的顺序。航班 4 没有较早的 A 类航班,因此它的序列为 1(在它之前有 0 个航班,我们加 1 使序列从 1 开始)。航班 9 之前有 1 个航班,所以我们有序列 2(之前有 1 个航班 + 1 个偏移量 = 2)。
我们需要为结果中的每个航班执行此操作,因此我们可以在查询的 select 部分包含一个子查询。 select 中的子查询与另一个 select 查询一样,但允许您在外部查询中使用数据,并对外部查询结果中返回的每一行执行此操作。
对于我们想要做的事情(根据他们的订单和他们的承运人找到航班的序号),子查询将比较每一行 id 与同一 table 中的所有行,如果它更小比当前行的 id,它是它之前的航班,并且将在子查询的结果中。 COUNT 聚合此子查询的结果,因此它是一个值。我们还确保子查询中的所有结果都与我们在主查询中查看的当前行的载体相匹配。我们必须为此子查询使用别名,因为它 select 来自同一个 table,否则会产生歧义,这就是为什么它使用别名 'f' 来将其与主查询区分开来.我们也可以给这个子查询的结果取一个名字flight_sequence_number,存储在一个新的列中。这将使您轻松了解所有航班的顺序,以及相对于同一承运人的航班顺序。
我已经在 Codecademy 上做这个练习好几天了,仍然无法理解背后的逻辑it.Below是练习和代码:
通过为航班提供基于时间的序列号(由承运人提供)来订购航班会很有趣。 例如,假设 flight_id 随着每个额外航班的增加而增加,我们可以使用以下查询按承运人、航班 ID 和序列号查看航班:
SELECT carrier, id,
(SELECT COUNT(*)
FROM flights f
WHERE f.id < flights.id
AND f.carrier=flights.carrier) + 1 AS flight_sequence_number
FROM flights;
我能理解f
是tableflights
的虚拟形式,但是f.id < flights.id
有什么作用呢?这是否意味着 SQL 将 f
中的每一行与 flights
中的每一行进行比较,例如
比较 MQ 17107 与 MQ 7869,
比较 MQ 17107 与 MQ 2205,
比较 MQ 17107 与 MQ 14979
……
将 MQ 7869 与 MQ 2205 进行比较,
比较 MQ 7869 与 MQ 14979
……
此外,这个 COUNT(*)
到底算什么?为什么 +1
?
这是结果图片:query result
如有任何帮助,我们将不胜感激。谢谢。
查询从 table 个航班中选择记录。对于每条记录,它选择承运人、id 和 flight_sequence_number.
因此,对于航班中的每条记录,都会执行子查询。它再次读取 table 个航班,但只记录具有相同承运人且航班 ID 小于主记录之一的记录。要说主查询记录和子查询记录,需要一两个table别名,否则两个记录都叫flight.id中的flight,就不清楚是哪一个了你正在谈论的一个。所以内部查询中的 table 得到别名 f。现在你可以比较 f.id < flights.id 和 f.carrier = flights.carrier.
COUNT(*) 因此计算低于其承运人的主记录航班 ID 的所有记录,从而对承运人的行进行编号。对于最小的 ID,您找不到更小的 ID,因此计数为 0,您添加一个,从而得到行号 1。对于第二小的 ID,您找到一个 ID 较小的记录,因此您得到计数 1,加 1 并得到行号 2等等。
如果您添加 order by 子句 ORDER BY carrier, id
,结果会更好看,因此您会按照使用的顺序显示结果。
如前所述,一些现代 DBMS 提供了分析功能,例如 ROW_NUMBER
并且查询变得更加简单:
select
carrier,
id,
row_number() over (partition by carrier order by id) as flight_sequence_number
from flights
order by carrier, id;
您有一个带有 flight_id 的航班列表,它告诉您所有航班相对于彼此的顺序。您正在查看的查询试图做的是获取仅与同一承运人的航班相关的每个航班的顺序。例如,如果我问你第 50 次航班是什么,那会很容易,因为你可以用 flight_id = 50 查找航班。但是如果我问你第 50 次美国航空公司的航班是什么,你不会我对 table 没有任何聚合或分区使用的情况有任何想法。
让我们看一个简单的 select 查询。如果你 select 给定类型 A 的所有运营商,你会得到这样的东西:
SELECT flight_id, carrier
FROM flights
WHERE carrier = A
flight_id, carrier
------------------
4, A
9, A
10, A
18, A
20, A
25, A
26, A
然而,当我们只查看承运人 A 时,flight_id
不再是序列号。ID 为 4 的航班不是我们结果的第 4 个航班(即航班 18)。然后我们可以聚合数据,这样我们就有了每个航班相对于同一承运人航班的顺序。所以我们要做的就是在每一行之前统计相同类型的航班数量,得到它的顺序。航班 4 没有较早的 A 类航班,因此它的序列为 1(在它之前有 0 个航班,我们加 1 使序列从 1 开始)。航班 9 之前有 1 个航班,所以我们有序列 2(之前有 1 个航班 + 1 个偏移量 = 2)。
我们需要为结果中的每个航班执行此操作,因此我们可以在查询的 select 部分包含一个子查询。 select 中的子查询与另一个 select 查询一样,但允许您在外部查询中使用数据,并对外部查询结果中返回的每一行执行此操作。
对于我们想要做的事情(根据他们的订单和他们的承运人找到航班的序号),子查询将比较每一行 id 与同一 table 中的所有行,如果它更小比当前行的 id,它是它之前的航班,并且将在子查询的结果中。 COUNT 聚合此子查询的结果,因此它是一个值。我们还确保子查询中的所有结果都与我们在主查询中查看的当前行的载体相匹配。我们必须为此子查询使用别名,因为它 select 来自同一个 table,否则会产生歧义,这就是为什么它使用别名 'f' 来将其与主查询区分开来.我们也可以给这个子查询的结果取一个名字flight_sequence_number,存储在一个新的列中。这将使您轻松了解所有航班的顺序,以及相对于同一承运人的航班顺序。