SQL相关子查询

时间:2016-09-22 21:05:37

标签: sql subquery correlated-subquery

我已经在Codecademy上进行了几天的练习,仍然无法理解它背后的逻辑。下面是练习和代码:

通过载体给予他们基于时间的序列号来订购航班会很有趣。 例如,假设每次增加航班时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是表flights的虚拟形式,但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

任何帮助将不胜感激。感谢。

2 个答案:

答案 0 :(得分:0)

查询从表格航班中选择记录。对于每条记录,它选择carrier,id和flight_sequence_number。

因此,对于航班中的每条记录,子查询都会被执行。它再次读取表格航班,但仅记录具有相同承运人且航班ID小于主记录的航班ID。为了讨论主查询记录和子查询记录,您需要一个或两个表别名,否则两个记录都将在flight.id中被称为flight,并且不清楚您正在谈论哪一个。因此内部查询中的表获取别名f。现在你可以比较f.id&lt; flights.id和f.carrier = flights.carrier。

COUNT(*)因此计算所有记录低于其主要记录的航空公司的航班ID,从而对航空公司的行进行编号。对于最小的ID,您找不到较小的ID,因此计数为0,并且您添加一个因此获得行号1.对于第二个最小的ID,您会找到一个ID较小的记录,因此您将获得计数1,添加1并获取第2行等等。

当您按照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;

答案 1 :(得分:0)

您有一个包含flight_id的航班列表,该列表会告诉您所有航班相对于彼此的顺序。您正在查看的查询正在尝试执行的操作,即每个航班的顺序仅与同一航空公司的航班相关。例如,如果我问你第50次飞行是什么,那就很容易,因为你可以用flight_id = 50查看航班。但是如果我问你第50次美国航空公司的航班是什么,你就不会有任何想法你得到的表没有一点聚合或使用分区。

让我们看一个简单的选择查询。如果你选择给定类型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查询一样,但允许您使用外部查询中的数据,并对外部查询结果中返回的每一行执行此操作。

对于我们想要做的事情(根据订单及其运营商查找航班的序列号),子查询将比较每个行的id与同一个表中的所有行,如果它小于当前行的id,它是一个航班,它将在子查询的结果中。 COUNT聚合此子查询的结果,因此它是一个值。我们还确保子查询中的所有结果与我们在主查询中查看的当前行的载体匹配。我们必须为这个子查询使用一个别名,因为它是从同一个表中选择的,否则会有歧义,这就是为什么它使用别名'f'来区分它与主查询。我们还可以将此子查询的结果赋予flight_sequence_number的名称,该名称存储在新列中。这将让您轻松了解所有航班的顺序,以及相对于同一航空公司的航班顺序。