2016-09-22 3 views
0

Je travaille sur cet exercice sur Codecademy pendant plusieurs jours et ne pouvait toujours pas comprendre la logique derrière it.Below est l'exercice et le code:SQL sous-requêtes en corrélation

Il serait intéressant de commander des vols en leur donnant un numéro de séquence basé sur le temps, par transporteur. Par exemple, en supposant des incréments flight_id à chaque vol supplémentaire, nous pourrions utiliser la requête suivante pour afficher les vols par transporteur, ID de vol et numéro de séquence:

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; 

Je peux comprendre que f est une forme virtuelle de la table flights , mais que fait f.id < flights.id? Est-ce que cela signifie que SQL compare chaque ligne f avec chaque ligne de flights comme

comparer MQ 17107 avec MQ 7869,

comparer MQ 17107 avec MQ 2205,

comparer MQ 17107 avec MQ 14979

......

comparer MQ 7869 avec MQ 2205,

comparer MQ 7869 wi e MQ 14979

......

A côté, qu'est-ce que COUNT(*) vraiment compte? Et pourquoi le +1?

C'est l'image de résultat: query result

Toute aide sera appréciée. Merci.

+1

Comptez le nombre de vols avant l'ID actuel et ajoutez 1. – jarlh

+1

Une bonne méthode de programmation a deux alias de table différents. Par exemple. f1 et f2 ici. – jarlh

+1

Avec [moderne SQL] (http://modern-sql.com/slides), cela peut être fait beaucoup plus facile en utilisant une simple fonction de fenêtre: 'row_number() over (partition support carrier par id)' - pas besoin d'un sous-requête. –

Répondre

0

La requête sélectionne les enregistrements des vols de table. Pour chaque enregistrement, il sélectionne carrier, id et flight_sequence_number.

Ainsi, pour chaque enregistrement dans les vols, la sous-requête est exécutée. Il lit à nouveau les vols de table, mais prend seulement les enregistrements avec le même transporteur et un ID de vol plus petit que celui de l'enregistrement principal. Pour parler de l'enregistrement de requête principal et de l'enregistrement de sous-requête, vous avez besoin d'un ou deux alias de table, sinon les deux enregistrements s'appelleraient flight comme dans flight.id, et vous ne saurez pas de qui vous parlez. Ainsi, la table de la requête interne obtient l'alias f. Maintenant, vous pouvez comparer f.id < flights.id et f.carrier = flights.carrier. COUNT (*) compte donc tous les enregistrements inférieurs à l'ID de vol d'un enregistrement principal pour son opérateur et numérote ainsi les lignes du transporteur. Pour le plus petit ID, vous ne trouvez pas d'ID plus petit, le compte est 0 et vous en ajoutez un, obtenant ainsi la ligne numéro 1. Pour le second plus petit, vous trouvez un enregistrement avec un ID plus petit. etc.

Les résultats sembleront mieux, quand vous ajoutez une commande par la clause ORDER BY carrier, id, ainsi vous montrerez les résultats dans l'ordre utilisé.

Comme il a été mentionné, plusieurs SGBD modernes offrent des fonctions analytiques, telles que ROW_NUMBER et la requête devient beaucoup plus simple:

select 
    carrier, 
    id, 
    row_number() over (partition by carrier order by id) as flight_sequence_number 
from flights 
order by carrier, id; 
+0

J'absorbe toujours vos réponses. Mais merci beaucoup. – Eva

0

Vous avez une liste des vols avec un flight_id qui vous indique la séquence de tous les vols l'un par rapport à l'autre.La requête que vous cherchez à faire est d'obtenir la séquence de chaque vol en relation uniquement avec les vols du même transporteur. Par exemple, si je vous demandais ce qui était le 50ème vol, ce serait facile puisque vous pouviez juste rechercher le vol avec flight_id = 50. Mais si je vous demandais quoi avec le 50th US Airlines, vous n'auriez aucune idée avec la table qui vous est donnée sans un peu d'agrégation ou d'utilisation de partitions.

Regardons une simple requête de sélection. Si vous sélectionnez tous les porteurs d'un type donné A, vous obtiendrez quelque chose comme ceci:

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 

Cependant flight_id n'est plus un numéro de séquence lorsque nous examinons seulement au transporteur A. Vol avec 4 ID n » t le 4ème vol de nos résultats (qui est le vol 18). Nous pourrions alors agréger les données de sorte que nous ayons la séquence de chaque vol par rapport aux vols du même transporteur. Donc, ce que nous devons faire est de compter le nombre de vols du même type avant chaque ligne pour obtenir sa séquence. Le vol 4 n'a pas de vols antérieurs de type A, donc il aurait une séquence de 1 (0 vols avant, nous ajoutons 1 pour que la séquence commence à 1). Le vol 9 a 1 vol devant lui donc nous avons la séquence 2 (1 vol avant + 1 décalage = 2).

Nous devons faire cela pour chaque vol dans nos résultats, donc nous pouvons inclure une sous-requête dans la partie select de notre requête. Une sous-requête dans la sélection sera comme une autre requête de sélection, mais vous permettra d'utiliser les données dans la requête externe, et cela pour chaque ligne retournée dans les résultats de la requête externe. Pour ce que nous voulons faire (trouver le numéro de séquence des vols en fonction de leur commande et de leur opérateur), la sous-requête compare chaque ID de ligne avec toutes les lignes de la même table, si elle est inférieure à l'ID de la ligne courante , c'est un vol avant et il sera dans les résultats de la sous-requête. COUNT regroupe les résultats de cette sous-requête de sorte qu'il s'agisse d'une seule valeur. Nous nous assurons également que tous les résultats de notre sous-requête correspondent au transporteur de la ligne actuelle que nous examinons dans notre requête principale. Nous devons utiliser un alias pour cette sous-requête car il est sélectionné dans la même table et serait ambigu dans le cas contraire, c'est pourquoi il utilise l'alias 'f' pour le distinguer de la requête principale. Nous pouvons également donner aux résultats de cette sous-requête un nom de flight_sequence_number, qui est stocké dans une nouvelle colonne. Cela vous permettra de connaître facilement le séquencement de tous les vols, ainsi que la séquence des vols par rapport au même transporteur.

+0

Merci de l'avoir rendu si clair. Cela clarifie tout pour moi. – Eva